#awk If else loop not working in ksh - linux

I have code where awk is piped to a clearcase command where If else loop is not working.
code is below :
#!/bin/ksh
export dst_region=$1
cleartool lsview -l | gawk -F":" \ '{ if ($0 ~ /Global path:/) { if($dst_region == "ABC" || $dst_region -eq "ABC") { system("echo dest_region is ABC");}
else { system("echo dest_region is not ABC"); } }; }'
But when I execute the above script the I get incorrect output,
*$ ksh script.sh ABCD
dest_region is ABC
$ ksh script.sh ABC
dest_region is ABC*
Could anyone please help on this issue ?

It would be useful if you explained exactly what you are trying to do but your awk script can be cleaned up a lot:
gawk -F":" -vdst_region="$1" '/Global path:/ { if (dst_region == "ABC") print "dest_region is ABC"; else print "dest_region is not ABC" }'
General points:
I have used -v to create an awk variable from the value of $1, the first argument to the script. This means that you can use it a lot more easily in the script.
awk's structure is condition { action } so you're using if around the whole one-liner unnecessarily
$0 ~ /Global path:/ can be changed to simply /Global path:/
the two sides of the || looked like they were trying to both do the same thing, so I got rid of the one that doesn't work in awk. Strings are compared using ==.
system("echo ...") is completely unnecessary. Use awk's built in print
You could go one step further and remove the if-else entirely:
gawk -F":" -vdst_region="$1" '/Global path:/ { printf "dest region is%s ABC", (dst_region=="ABC"?"":" not") }'

Related

Why AWK uses my arguments as input file

I'm writing an awk script to let it parse something for me. For the purpose of convenience, I want the awk script to be executable in linux. Here are my codes:
#!/usr/bin/awk -f
BEGIN {
FILENAME=ARGV[1]
sub_name=ARGV[2]
run=ARGV[3]
count=0
}
{
if ($4 == "ARGV[2]" && $8 == ARGV[3])
{
print $15
count=count+1
}
}
END {
print count
}
When I issue my awk script in linux such as:
./my_script 001.log type1 2
awk will say:
awk: ./awk_script:23: fatal: cannot open file `type1' for reading (No such
file or directory)
I just want to let argument "type1" as a variable in my script, not a input file for parsing. How can I don't let awk treat it as an imput file?
Thank you,
Don't use a shebang to execute the awk script as it just complicates things:
/usr/bin/awk -v sub_name="$2" -v run="$3" '
{
if ($4 == sub_name && $8 == run)
{
print $15
count=count+1
}
}
END {
print count
}
' "$1"
Note that your script could be cleaned up a bit:
/usr/bin/awk -v sub_name="$2" -v run="$3" '
($4 == sub_name) && ($8 == run) {
print $15
count++
}
END { print count+0 }
' "$1"
Delete the non-file options from ARGV:
delete ARGV[2]
delete ARGV[3]
if you want to use them as variables then you have to use the -v argument. The way you are trying to do it , suggests that the second argument is an input/output file

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.

Why a ~ in double quotes within awk caused syntax error

I was going write script for my device.
Here is my initial code:
dev_name=random_sting
major=`awk "\$2 ~ /^${dev_name}\$/ { print \$1 }" /proc/devices`
Then an error happen
awk: ~ /^random_string$/ { print }
awk: ^ syntax error
Meanwhile, I did an experiment:
var1=random_string
echo "\$ /^$var1\$/ \$"
The output was
$ /^random_string$/ $
It seems the syntax should be correct, can anybody give me an answer?
You need additional escapes inside back ticks. Try using major=$( .. ) instead..
In this case you can also bypass the need for escaping, using the -v option of awk, like this
major=`awk -v dev="$dev_name" '$2 ~ dev { print $1 }' /proc/devices`
Your expression inside backticks will pass through 2 shells/unescape stages.
awk "\$2 ~ /^${dev_name}\$/ { print \$1 }" /proc/devices
...will be expanded and unescaped by your bash to...
awk "$2 ~ /^random_string$/ { print $1 }" /proc/devices`
...which the shell started by the backticks will expand and unescape again to...
awk "~ /^random_string$/ { print }" /proc/devices`
...since $1 and $2 are not defined.
What you want to do is to escape $1 and $2 twice;
awk "\\\$2 ~ /^${dev_name}\$/ { print \\\$1 }" /proc/devices
...to make the executed end result...
awk "$2 ~ /^random_string\$/ { print $1 }" /proc/devices
That's how I solve the problem.
Let's scrutinize this line:
dev_name='loop' ; major=` awk "\\\$2 ~ /^\${dev_name}\\\$/ { print \\\$1 }" /proc/devices` ; echo $major
bash expand it twice, and double quote is not expanded between backticks (`), so this is going to output the proper outcome.

i want to combine two awk scripts

I have two with AWK which works perfectly
myScript3.awk
#!/usr/bin/awk -f
BEGIN {
FS=">|</"
OFS=","
}
{
data[count++] = $2
ptint $2
}
END{
print data[2],data[6],data[3], FILENAME
}
The above script will scan the xml document and return the 2nd, 6th, 3rd element along with file name.
for filename in *.xml
do
awk -f myscript3.awk $filename >> out.txt
done
The above script will scan the entire folder and list down xml files and then execute myscript.
i have to merge these two scripts as one.
Thanks for your help
Note about calling conventions: if you're running the script as awk -f script you do not need the shabang (#!) line at the beginning. Alternatively you can run it with the shabang as ./script if script is executable.
Answer
awk has BEGINFILE and ENDFILE, replace BEGIN/END with them and give the xml files as an argument, the following should work:
Edit
As noted by Dennis in the comments below, there's no need for BEGINFILE. Also note that this requires a fairly recent version of GNU awk to work.
myScript3.awk
BEGIN {
FS=">|</"
OFS=","
}
{
data[count++] = $2
print $2
}
ENDFILE {
print data[2],data[6],data[3], FILENAME
}
Run it like this:
awk -f myscript.awk *.xml
#!/bin/bash
AWKPROG='BEGIN {FS=">|</" OFS=","}
{ data[count++] = $2; ptint $2 }
END {print data[2], data[6], data[3], FILENAME}'
for filename in *.xml;do awk $AWKPROG $filename; done >> out.txt
Warning: Untested.

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