Awk getting results back with multiple columns - linux

I have a function that searches one column for one string, how would I allow it so I can provide my script with multiple columns to search with multiple search strings?
awk -v s=$1 -v c=$2 '$c ~ s { print $0 }' $3
Thanks

You can use an or clause in the pattern:
awk -v s=$1 -v c=$2 '$c ~ s || $3 == "foo"' $3
will print all lines in the file $3 in which column $2 matches the string $1 or $3 matches the string "foo". Note that the action "print $0" is redundant, and is the default if no action is given.

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

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

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.

Filling a shell script array with data

I want to extract some data from a file and save it in an array, but i don't know how to do it.
In the following I'm extracting some data from /etc/group and save it in another file, after that I print every single item:
awk -F: '/^'$GROUP'/ { gsub(/,/,"\n",$4) ; print $4 }' /etc/group > $FILE
for i in `awk '{ print $0 }' $FILE`
do
echo "member: "$i" "
done
However, I don't want to extract the data into a file, but into an array.
members=( $(awk -F: '/^'$GROUP':/ { gsub(/,/,"\n",$4) ; print $4 }' /etc/group) )
The assignment with the parentheses indicates that $members is an array. The original awk command has been enclosed in $(...), and the colon added so that if you have group and group1 in the file, and you look for group, you don't get the data for group1 too. Of course, if you wanted both entries, then you drop the colon I added.
j=0
for i in `awk '{ print $0 }' $FILE`
do
arr[$j] = $i
j=`expr $j + 1`
done
arr=($(awk -F: -v g=$GROUP '$1 == g { gsub(/,/,"\n",$4) ; print $4 }' /etc/group))

Awk Search file for string

I have implimented a function that searches a column in a file for a string and it works well. What I would like to know how do I modify it to search all the columns fr a string?
awk -v s=$1 -v c=$2 '$c ~ s { print $0 }' $3
Thanks
If "all the columns" means "the entire file" then:
grep $string $file
Here is an example of one way to modify your current script to search for two different strings in two different columns. You can extend it to work for as many as you wish, however for more than a few it would be more efficient to do it another way.
awk -v s1="$1" -v c1="$2" -v s2="$3" -v c2="$4" '$c1 ~ s1 || $c2 ~ s2 { print $0 }' "$5"
As you can see, this technique won't scale well.
Another technique treats the column numbers and strings as a file and should scale better:
awk 'FNR == NR {strings[++c] = $1; columns[c] = $2; next}
{
for (i = 1; i <= c; i++) {
if ($columns[i] ~ strings[i]) {
print
}
}
}' < <(printf '%s %d\n' "${searches[#]}") inputfile
The array ${searches[#]} should contain strings and column numbers alternating.
There are several ways to populate ${searches[#]}. Here's one:
#!/bin/bash
# (this is bash and should precede the AWK above in the script file)
unset searches
for arg in "${#:1:$#-1}"
do
searches+=("$arg")
shift
done
inputfile=$1 # the last remaining argument
# now the AWK stuff goes here
To run the script, you'd do this:
$ ./scriptname foo 3 bar 7 baz 1 filename
awk -v pat="$string" '$0 ~ pat' infile

Resources