Linux shell script: Pass variable from stdin to awk [duplicate] - linux

This question already has answers here:
BASH: How to use a variable as regex in AWK
(3 answers)
How to match a pattern given in a variable in awk?
(3 answers)
Closed 5 years ago.
I have a comma-separated .txt file structured like this:
ABC,NAME1,LASTNAME1
DEF,NAME2,LASTNAME2
GHI,NAME3,LASTNAME3
When running:
$ ./script.sh file.txt
#!/bin/bash
awk -F, '/NAME1/{print $3}' "$1"
I get my desired output:
LASTNAME1
When trying to replace NAME1 by passing a variable to awk:
$ ./script.sh file.txt NAME1
#!/bin/bash
awk -v n="$2" -F, '/$n/{print $3'} "$1"
I do not get any output at all. I checked, that $2 entered in bash really is NAME1. What am I missing?

Variable names in Awk are not prefixed with a $,
so it should be just n instead of $n.
Also, you cannot use variables inside a /.../ expression.
You can write like this:
awk -v n="$2" -F, '$0 ~ n {print $3}' "$1"
Btw, if the n parameter should match the value in the 2nd column exactly,
then it's better to use an exact matching condition with == on $2:
awk -v n="$2" -F, '$2 == n {print $3}' "$1"

Related

AWK comparing two variables that are strings [duplicate]

This question already has answers here:
How do I use shell variables in an awk script?
(7 answers)
Closed 3 years ago.
I want to get a user intput at the begining af the script (as an argument) and then compare it to a string using awk !
I'm using -v to add the variable into the awk command(by the way the input is STRING)
But for some reason it won't show the expected output !
And i know that the problem is on the variable that i inserted into the awk command , because if i put instead of the variable the string that i want to find, the specific one that i know that is inside the file , it will find it and print the result i want.
I will show you code !
awk -v x=$a -F '[:,]' ' { if ($1 == $a ) print $5 }' /etc/passwd
i have also tried:
awk -v x="$a" -F '[:,]' ' { if ($1 == "$a" ) print "$5" }' /etc/passwd
But nothing. I cannot find the solution.
A clarification here. I have made the correct seperation and i know the file what it includes!
And here an example that works without the variable
awk -v x=$a -F '[:,]' ' { if ($1 == "psz" ) print $5 }' /etc/passwd
psz is the string that i have set before the awk command at the a variable ( a="psz" ) like that.
And it is what i know that is inside the /etc/passwd at the first field ($1) !!
You should use instead of this:
awk -v x=$a -F '[:,]' ' { if ($1 == $a ) print $5 }' /etc/passwd
this:
awk -v x=$a -F '[:,]' ' { if ($1 == x ) print $5 }' /etc/passwd
You define x as a variable and this should be used in awk

Replace string in a file from a file [duplicate]

This question already has answers here:
Difference between single and double quotes in Bash
(7 answers)
Closed 5 years ago.
I need help with replacing a string in a file where "from"-"to" strings coming from a given file.
fromto.txt:
"TRAVEL","TRAVEL_CHANNEL"
"TRAVEL HD","TRAVEL_HD_CHANNEL"
"FROM","TO"
First column is what to I'm searching for, which is to be replaced with the second column.
So far I wrote this small script:
while read p; do
var1=`echo "$p" | awk -F',' '{print $1}'`
var2=`echo "$p" | awk -F',' '{print $2}'`
echo "$var1" "AND" "$var2"
sed -i -e 's/$var1/$var2/g' test.txt
done <fromto.txt
Output looks good (x AND y), but for some reason it does not replace the first column ($var1) with the second ($var2).
test.txt:
"TRAVEL"
Output:
"TRAVEL" AND "TRAVEL_CHANNEL"
sed -i -e 's/"TRAVEL"/"TRAVEL_CHANNEL"/g' test.txt
"TRAVEL HD" AND "TRAVEL_HD_CHANNEL"
sed -i -e 's/"TRAVEL HD"/"TRAVEL_HD_CHANNEL"/g' test.txt
"FROM" AND "TO"
sed -i -e 's/"FROM"/"TO"/g' test.txt
$ cat test.txt
"TRAVEL"
input:
➜ cat fromto
TRAVEL TRAVEL_CHANNEL
TRAVELHD TRAVEL_HD
➜ cat inputFile
TRAVEL
TRAVELHD
The work:
➜ awk 'BEGIN{while(getline < "fromto") {from[$1] = $2}} {for (key in from) {gsub(key,from[key])} print}' inputFile > output
and output:
➜ cat output
TRAVEL_CHANNEL
TRAVEL_CHANNEL_HD
➜
This first (BEGIN{}) loads your input file into an associate array: from["TRAVEL"] = "TRAVEL_HD", then rather inefficiently performs search and replace line by line for each array element in the input file, outputting the results, which I piped to a separate outputfile.
The caveat, you'll notice, is that the search and replaces can interfere with each other, the 2nd line of output being a perfect example since the first replacement happens. You can try ordering your replacements differently, or use a regex instead of a gsub. I'm not certain if awk arrays are guaranteed to have a certain order, though. Something to get you started, anyway.
2nd caveat. There's a way to do the gsub for the whole file as the 2nd step of your BEGIN and probably make this much faster, but I'm not sure what it is.
you can't do this oneshot you have to use variables within a script
maybe something like below sed command for full replacement
-bash-4.4$ cat > toto.txt
1
2
3
-bash-4.4$ cat > titi.txt
a
b
c
-bash-4.4$ sed 's|^\s*\(\S*\)\s*\(.*\)$|/^\2\\>/s//\1/|' toto.txt | sed -f - titi.txt > toto.txt
-bash-4.4$ cat toto.txt
a
b
c
-bash-4.4$

how to use awk's $0 variables in the shell file

1.my shell file is
[root#node3 script]# cat hi.sh
#!/bin/bash
strings="sdsf sdsda sdsadx"
echo `awk "{print substr($0,0,9)}"<<<$strings`
2.exe my shell file
[root#node3 script]# sh hi.sh
awk: {print substr(hi.sh,0,9)}
awk: ^ syntax error
awk: 致命错误: 0 是 substr 的无效参数个数
so how to use the awk's $0 in shell file ?
the $0 default file's name .
another ques. i want use the var $0 about awk but the another $variable in the shell file.what should i do ?
$ cat hi.sh
#!/bin/bash
strings="sdsf sdsda sdsadx"
num=9
echo \`awk '{print substr($0,0,$num)}' <<< $strings\`
The problem with your script is use of double quotes in awk. Replace them with single quotes.
When you use double quotes, the $0 inside it is treated as first argument to the script, which in this case is script name hi.sh. If you use single quotes, you can use $0 as awk argument to display whole row.
Also echo is not needed here, you can just use awk '{print substr($0,0,9)}' <<< $strings
$ cat hi.sh
#!/bin/bash
strings="sdsf sdsda sdsadx"
#echo `awk '{print substr($0,0,9)}' <<< $strings` --echo not needed
awk '{print substr($0,0,9)}' <<< $strings
$
$ sh hi.sh
sdsf sdsd

awk command not working as expected when bash variable is used inside

I tried to use bash variable inside awk by creating a variable in awk command as below. but it does not work it seems
b=hi
$ echo "hihello" |awk -v myvar=$b -F"$0~myvar" '{print $2}'
Actual Output is :
<empty / nothing printed >
Expected output is :
hello
Why don't you do this:
b=hi ; echo "hihello" | awk -F"$b" '{print $2}'
hello
Try the below awk command. Put the Field Separator inside BEGIN block.
$ b=hi; echo "hihello" | awk -v myvar=$b 'BEGIN{FS=myvar}{print $2}'
hello
It sets the value of myvar variable to the Field Separator. Thus inturn printing the second column will give you the string hello

bash, extract string from text file with space delimiter

I have a text files with a line like this in them:
MC exp. sig-250-0 events & $0.98 \pm 0.15$ & $3.57 \pm 0.23$ \\
sig-250-0 is something that can change from file to file (but I always know what it is for each file). There are lines before and above this, but the string "MC exp. sig-250-0 events" is unique in the file.
For a particular file, is there a good way to extract the second number 3.57 in the above example using bash?
use awk for this:
awk '/MC exp. sig-250-0/ {print $10}' your.txt
Note that this will print: $3.57 - with the leading $, if you don't like this, pipe the output to tr:
awk '/MC exp. sig-250-0/ {print $10}' your.txt | tr -d '$'
In comments you wrote that you need to call it in a script like this:
while read p ; do
echo $p,awk '/MC exp. sig-$p/ {print $10}' filename | tr -d '$'
done < grid.txt
Note that you need a sub shell $() for the awk pipe. Like this:
echo "$p",$(awk '/MC exp. sig-$p/ {print $10}' filename | tr -d '$')
If you want to pass a shell variable to the awk pattern use the following syntax:
awk -v p="MC exp. sig-$p" '/p/ {print $10}' a.txt | tr -d '$'
More lines would've been nice but I guess you would like to have a simple use awk.
awk '{print $N}' $file
If you don't tell awk what kind of field-separator it has to use it will use just a space ' '. Now you just have to count how many fields you have got to get your field you want to get. In your case it would be 10.
awk '{print $10}' file.txt
$3.57
Don't want the $?
Pipe your awk result to cut:
awk '{print $10}' foo | cut -d $ -f2
-d will use the $ als field-separator and -f will select the second field.
If you know you always have the same number of fields, then
#!/bin/bash
file=$1
key=$2
while read -ra f; do
if [[ "${f[0]} ${f[1]} ${f[2]} ${f[3]}" == "MC exp. $key events" ]]; then
echo ${f[9]}
fi
done < "$file"

Resources