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.
Related
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
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") }'
I think the question speaks for itself. I have two text files: file1 and file2. Here is a sample code with awk inside a bash script:
EDIT: I am using gnu awk
My Script:
val=3
awk 'if ("'$val'" == "3")
print "Hello" >> "'$PWD/file1.txt'"
else
print "Goodbye" #append to file1.txt and file2.txt
'
I don't want something like this:
val=3
awk 'if ("'$val'" == "3")
print "Hello" >> "'$PWD/file1.txt'"
else {
print "Goodbye" >> "'$PWD/file1.txt'"
print "Goodbye" >> "'$PWD/file2.txt'"
}'
I know that in bash you can use tee to pipe to multiple files. Can it be used in gnu awk? If so then how? Is there another way in gnu awk?
The GNU Awk manual show an example of how to simulate tee with awk. This might be a good starting point.
The basic idea will be to store the various output file names in an array -- and then to loop over this array to send the output on each file in its turn. In your case something like that (I type directly in SO -- you have to adapt/fix according to your needs, of course):
BEGIN {
output[0] = "'$PWD/file1.txt'"
output[1] = "'$PWD/file1.txt'"
...
}
{
for (i in output)
print "Goodbye!" >> output[i]
}
I know that in bash you can use tee to pipe to multiple files. Can it be used in gnu awk?
If a non-awk only solution is acceptable, an other option will be to redirect some filedescriptor to tee in the outer bash scrip and then send output to that fd from awk when required. Here is a simple example:
#!/bin/bash
exec 4<> >(tee file1.txt file2.txt)
awk '{ print NR; # send only to stdout
print "READ:" $0 >> "/dev/fd/4"; # send to `tee`
}'
That produces:
sh$ (echo a; echo b) | ./a.sh
1
2
READ:a
READ:b
sh$ cat file1.txt
READ:a
READ:b
sh$ cat file2.txt
READ:a
READ:b
Your awk script is wrong in the way it access the value of shell variables and you're putting the whole script in the condition section and so will get undesirable side effects if not syntax errors.
Your script:
val=3
awk 'if ("'$val'" == "3")
print "Hello" >> "'$PWD/file1.txt'"
else
print "Goodbye" #append to file1.txt and file2.txt
'
should instead have been written as:
val=3
awk -v val="$val" -v pwd="${PWD}/" '{
if (val == 3)
print "Hello" >> (pwd "file1.txt")
else
print "Goodbye" #append to file1.txt and file2.txt
}'
to be syntactically correct. To expand it to print to multiple files is:
val=3
awk -v val="$val" -v pwd="${PWD}/" '{
if (val == 3) {
print "Hello" >> (pwd "file1.txt")
}
else {
print "Goodbye" >> (pwd "file1.txt")
print "Goodbye" >> (pwd "file2.txt")
}
}'
Or:
val=3
awk -v val="$val" -v pwd="${PWD}/" '
BEGIN { split("file1 file2",files) }
{
if (val == 3)
print "Hello" >> (pwd "file1.txt")
else
for (f in files)
print "Goodbye" >> (pwd files[f] ".txt")
}'
I am trying to search for a pattern and from the results i am extracting just the second column. The command works well in command line but not inside a bash script.
#!/bin/bash
set a = grep 'NM_033356' test.txt | awk '{ print $2 }'
echo $a
It doesnt print any output at all.
Input
NM_033356 2
NM_033356 5
NM_033356 7
Your code:
#!/bin/bash
set a = grep 'NM_033356' test.txt | awk '{ print $2 }'
echo $a
Change it to:
#!/bin/bash
a="$(awk '$1=="NM_033356"{ print $2 }' test.txt)"
echo "$a"
Code changes are based on your sample input.
.......
a="$(awk '/NM_033356/ { print $2 }' test.txt)"
Try this:
a=`grep 'NM_033356' test.txt | awk '{ print $2 }'`
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.