AWK comparing two variables that are strings [duplicate] - string

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

Related

awk with bash variable along with condition to be checked

I need to search and replace a pattern from file
[ec2_server]
server_host=something
[list_server]
server_host=old_name
to
[ec2_server]
server_host=something
[list_server]
server_host=new_name
I'm able to get it working with
awk '/\[list_server]/ { print; getline; $0 = "server_host=new_name" } 1'
But I'm trying to parameterize the search pattern, the parameter name to change and the parameter value to change.
PATTERN_TO_SEARCH=[list_server]
PARAM_NAME=server_host
PARAM_NEW_VALUE=new_name
But it is not working when I parameterize and pass the variables to awk
awk -v patt=$PATTERN_TO_SEARCH -v parm=$PARAM_NAME -v parmval=$PARAM_NEW_VALUE '/\patt/ { print; getline; $0 = "parm=parmval" } 1' file.txt
You have two instances of the same problem: you're trying to use a
variable name inside a string value. Awk can't read your mind: it
can't intuit that sometimes when your write "HOME" you mean "print the
value of the variable HOME" and other times you mean "print the word
HOME".
We need to make two separate changes:
First, to use a variable in your search pattern, you can use
syntax like this:
awk -v patt='some text' '$0 == patt {print}'
(Note that here we're using an equality match, ==; you can also use a regular expression match, ~, but in this particular case that would only complicate things).
With your example file content, running:
awk -v patt='[list_server]' '$0 == patt {print}' file.txt
Produces:
[list_server]
Next, when you write $0 = "parm=parmval", you're setting $0 to the literal string parm=parmval. If you want to perform variable substitution, consider using sprintf():
awk \
-v patt="$PATTERN_TO_SEARCH" \
-v parm="$PARAM_NAME" \
-v parmval="$PARAM_NEW_VALUE"\
'
$0 == patt { print; getline; $0 = sprintf("%s=%s\n", parm, parmval) } 1
' file.txt
Which gives us:
[ec2_server]
server_host=something
[list_server]
server_host=new_server
Have your awk code in following way, as experts recommend not to use getline(since it has edge cases in its use). So I am going with find the string and then set flag(custom variable made by me in program) and then print the line accordingly with using regex along with passed value from shell variable.
Along with matching and printing the new value we need to set field separator also to fetch correct value and replace/print it with new value. So I made field separator as = here for whole Input_file. By doing this approach you need not to pass any variable which has server_host value in it, since its already present in Input_file so we can take it from there.
awk solution with mentioning value within awk variable itself and then check regex in main program of awk for comparison.
awk -v var="list_server" -v newVal="NEW_VALUE" '
BEGIN{ FS=OFS="=" }
$0 ~ "^\\[" var "\\]$"{
found=1
print
next
}
found{
print $1 OFS newVal
found=""
next
}
1
' Input_file
OR awk solution to get value from shell variable and then use regex inside awk to match condition:
varS="list_server" ##Shell variable
newvalue="NEW_VALUE" ##Shell variable
awk -v var="$varS" -v newVal="$newvalue" '
BEGIN{ FS=OFS="=" }
$0 ~ "^\\[" var "\\]$"{
found=1
print
next
}
found{
print $1 OFS newVal
found=""
next
}
1
' Input_file
$ awk -v pat="$PATTERN_TO_SEARCH" -v parm="$PARAM_NAME" -v parmval="$PARAM_NEW_VALUE" '
f{$0=parm"="parmval; f=0} $0==pat{f=1} 1
' file
[ec2_server]
server_host=something
[list_server]
server_host=new_name
This makes the assumption "${PARAM_NAME}" immediately follows the search pattern row :
_P2S_='[list_server]'
_PNM_='server_host'
_PNV_='new_name'
echo "${...input...}" | gtee >( gpaste - | gcat -b >&2; echo ) | gcat - |
{m,n,g}awk -v __="${_P2S_}=${_PNM_}=${_PNV_}" -F= 'BEGIN {
$(_-=_)=__;___= $(_ = NF); FS ="^"(OFS = $--_ FS)
__= $-(_+=-_--) } (NR-_)< NF ? ($NF =___)^(_-=_) :_=NR*(-!!_)^(__!=$!_)' |
gcat -b | gcat -n | ecp
1 [ec2_server]
2 server_host=something
3 [list_server]
4 server_host=old_name
1 1 [ec2_server]
2 2 server_host=something
3
4 3 [list_server]
5 4 server_host=new_name

How do I make the Awk work with Bash array variables in a shell script?

user=(`cat < usernameSorted.txt`)
for (( i=0; i<${#user[#]}; i++ ))
do
`awk '$1 == "${user[$i]}"{print $NF}' process.txt > CMD$i.txt`
done
This is how I had coded for using user array elements as the awk specifier. How do I insert ${user[$i]} into the AWK command.
As I noted in a comment, you have your Awk script enclosed in single quotes; your shell variables will not be expanded inside the single quotes. On the whole, that's good; $NF is not one of your shell variables.
You'll probably need to use a variation on the theme of:
awk -v user="${user[$i]}" '$1 == user { print $NF }' process.txt > "CMD$i.txt"
where you refer to user as an Awk variable set from "${user[$i]}" on the command line.
There are a few other oddities in the script. The < is not necessary with cat. You could avoid the Bash array by using:
i=0
for user in $(cat usernameSorted.txt)
do
awk -v user="$user" '$1 == user { print $NF }' process.txt > "CMD$i.txt"
((i++))
done
You do not want the back-ticks around the Awk command. Fortunately, you redirect the standard output to a file so the string executed is empty, and nothing happens.

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

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"

Bash Script Awk Condition

i have a problem with this code.. i can't figure out what i have to write as condition to cut my file with awk.
i=0
while [ $i -lt 10 ]; #da 1 a 9, Ap1..Ap9
do
case $i in
1) RX="54:75:D0:3F:1E:F0";;
2) RX="54:75:D0:3F:4D:00";;
3) RX="54:75:D0:3F:51:50";;
4) RX="54:75:D0:3F:53:60";;
5) RX="54:75:D0:3F:56:10";;
6) RX="54:75:D0:3F:56:E0";;
7) RX="54:75:D0:3F:5A:B0";;
8) RX="54:75:D0:3F:5F:90";;
9) RX="D0:D0:FD:68:BC:70";;
*) echo "Numero invalido!";;
esac
echo "RX = $RX" #check
awk -F, '$2 =="$RX" { print $0 }' File1 > File2[$i] #this is the line!
i=$(( $i + 1 ))
done
the command echo prints correctly but when i use the same "$RX" as condition in AWK it doesn't work (it prints a blank page).
my File1 :
1417164082794,54:75:D0:3F:53:60,54:75:D0:3F:1E:F0,-75,2400,6
1417164082794,54:75:D0:3F:56:10,54:75:D0:3F:1E:F0,-93,2400,4
1417164082794,54:75:D0:3F:56:E0,54:75:D0:3F:1E:F0,-89,2400,4
1417164082794,54:75:D0:3F:5A:B0,54:75:D0:3F:1E:F0,-80,2400,4
1417164082794,54:75:D0:3F:53:60,54:75:D0:3F:1E:F0,-89,5000,2
could you tell me the right expression "awk -F ..."
thank you very much!
To pass variables from shell to awk use -v:
awk -F, -v R="$RX" '$2 ==R { print $0 }' File1 > File2[$i]
#Ricky - any time you write a loop in shell just to manipulate text you have the wrong approach. It's just not what the shell was created to do - it's what awk was created to do and the shell was created to invoke commands like awk.
Just use a single awk command and instead of reading File 10 times and switching on variables for every line of the file, just do it all once, something like this:
BEGIN {
split(file2s,f2s)
split("54:75:D0:3F:1E:F0\
54:75:D0:3F:4D:00\
54:75:D0:3F:51:50\
54:75:D0:3F:53:60\
54:75:D0:3F:56:10\
54:75:D0:3F:56:E0\
54:75:D0:3F:5A:B0\
54:75:D0:3F:5F:90\
D0:D0:FD:68:BC:70", rxs)
for (i in rxs) {
rx2file2s[rxs[i]] = f2s[i]
}
}
{
if ($2 in rx2file2s) {
print > rx2file2s[$2]
}
else {
print NR, $2, "Numero invalido!" | "cat>&2"
}
}
which you'd then invoke as awk -v file2s="${File2[#]}" -f script.awk File1
I say "something like" because you didn't provide any sample input (File1 contents) or expected output (File2* values and contents) so I couldn't test it but it will be very close to what you need if not exactly right.

Want to use a variable inside if outside of it in awk command

awk < MigStat.stat -F: '{ if ($a == "load")b=8; } $1 == "D0001" && FNR== '$c' {print $b}'
now i want the print the value present in column $b but in this case it prints the whole line.
What i want do is use the value of b from the if statement to print the value in that column
To pass in values use the -v option:
awk -F: -v a=2 -v c=10 '$a=="load"{b=8}$1=="D0001"&&FNR==c{print $b}' MigStat
Notes:
To pass in variables use the -v option of awk.
awk reads file you don't need to use redirection.
The structure of awk is condition{block}.
awk initialises variable to 0 so if b hasn't been set in the block $a=="load"{b=8} then {print $b} will be {print $0} where $0 is the whole line.
You don't need redundantly assigning b=8 . If the script is like what you posted there, you don't need the $b at all.
if $a, $c are shell variables:
awk -F: -v a="$a" -v c="$c" 'a=="load"&&$1=="D0001"&&NR==c{print $8;exit}' MigStat.stat
and better after print $8 call exit; to stop awk processing further lines.

Resources