awk syntax error help identifying - bash

I can't seem to identify where the syntax error is ..I've tried to these 2 statements but nothing gets written to the 'BlockedIPs' file. Can someone please help? Thanks!
awk '/ (TCP|UDP) / { split($5, addr, /:/); cmd = "/Users/user1/Scripts/geoiplookup " addr[1] | awk '{print $4, $5, $6}'; cmd | getline rslt; close(cmd); print $1, $2, $3, rslt }' < "$IP_PARSED" >> "$BlockedIPs"
awk '/ (TCP|UDP) / { split($5, addr, /:/); cmd = "/Users/user1/Scripts/geoiplookup " addr[1] " | awk '{print $4, $5, $6}'" ; cmd | getline rslt; close(cmd); print $1, $2, $3, rslt }' < "$IP_PARSED" >> "$BlockedIPs"

Your problem is primarily with quoting and stems from the fact that you're trying to call AWK from within an AWK one-liner. It's certainly possible, but getting the quoting right would be very tricky.
It would be much better if you retrieved the complete output of geoiplookup into a variable then did a split() to get just the data you need. Something like:
awk '/ (TCP|UDP) / { split($5, addr, /:/); cmd = "/Users/user1/Scripts/geoiplookup " addr[1]; cmd | getline rslt; split(rslt, r); close(cmd); print $1, $2, $3, r[4], r[5], r[6] }' < "$IP_PARSED" >> "$BlockedIPs"

Related

awk dynamic field list to print

what is the best way to do something like
awk '{ print $1, $3, $5 }'
but in a dynamic way?
The case is that the last field to print in only known at runtime.
so it might be $1, $3, $5, it might also be $1, $3, $5, $7, $9 or even more
my first trial is like:
awk -v MAX=7 '{for (i = 2; i < MAX; i+=2) {print i,$i} }'
but it print one field in a line:
a[2]
a[4]
a[6]
instead of
a[2] a[4] a[6]
is there a better way to achieve this?
Thanks for all your suggestion. :)
One follow-up question.
at runtime, I already have the sequence available, say MyArray=(2 4 6 8)
is there a way to "pass" this array into awk and ask awk to print $2 $4 $6 $8 ?
so that I can save one for-loop inside awk
Using printf omits the newlines but you'll need to use a format string and add a newline yourself:
awk -v MAX=7 '{
for (i = 2; i < MAX; i+=2) {
printf "a[%d]=%s " i, $i
}
printf "\n"
}'
Note that the above example includes a trailing space after the last a[N]=VAL on each line. If you want to omit it, you can use something like:
awk -v MAX=7 '{
print_num = 0
for (i = 2; i < MAX; i+=2) {
if ( print_num++ > 0 ) { printf " " }
printf "a[%d]=%s" i, $i
}
printf "\n"
}'
With an array A you can do
for i in $(seq 0 2 ${#A}); do
printf "%s " ${A[i]}
done | sed 's/ $/\n/'

Print a column in awk if it matches, if not then still print the line (without that column)

I'm trying to do some filtering with awk but I'm currently running into an issue. I can make awk match a regex and print the line with the column but I cannot make it print the line without the column.
awk -v OFS='\t' '$6 ~ /^07/ {print $3, $4, $5, $6}' file
Is currently what I have. Can I make awk print the line without the sixth column if it doesn't match the regex?
Set $6 to the empty string if the regex doesn't match. As simple as that. This should do it:
awk -v OFS='\t' '{ if ($6 ~ /^07/) { print $3, $4, $5, $6 } else { $6 = ""; print $0; } }' file
Note that $0 is the entire line, including $2 (which you didn't seem to use). It will print every column except the 6th column.
If you just want to print $3, $4 and $5 when there isn't a match, use this instead:
awk -v OFS='\t' '{ if ($6 ~ /^07/) print $3, $4, $5, $6; else print $3, $4, $5 }' file

bash- replace empty field with . in piped statement

I'm looping over a list of files, while for each file im scanning for specific things to grep out.
# create .fus file
grep DIF $file | awk '{
if ( $7 != $13 )
print $4, "\t", $5, "\t", $20, "\t", $10, "\t", $11, "\t", $22, "\t", "Null";
}' > $file_name.fus
# create .inv_fus file
grep DIF $file | awk '{
if ( $7 == $13 )
print $4, "\t", $5, "\t", $20, "\t", $10, "\t", $11, "\t", $22, "\t", "Null";
}' > $file_name.inv_fus
# create .del file
echo -e '1\t1\t1\t1' > ${file_name}.del
echo -e '1\t1\t1\t3' >> ${file_name}.del
grep DEL ${file} | awk '{print $4, "\t", $5, "\t", $12, "\t", "2"}' >> ${file_name}.del
The first awk checks if the values of column 7 and 13 are different, if they are, write to file.
The second awk checks if hte values are the same, if they are, write to file. The third creates a file with 2 lines always the same, and the rest filled in by lines containing 'DEL'.
The output files I use to generate a plot, but this fails because some fields are empty. How can I change my code (I guess the awk statement ?) so that it checks for empty fields (for columns 4, 5, 20, 10, 11 and 22) and replace empty columns with dots '.' ?
Like the other response has said, there's a lot of simplification that could happen here, but without knowing input or expected output its hard to comment on what changes would be beneficial.
Regardless, the question seems to boil down to replacing empty fields with dots in your output for some process down the line. Adding a function like this to your awk scripts would seem to do the trick:
function clean() {
for(i = 1; i <= NF; i++) { if($i==""){$i="."}; }
}
For example, given this input in test.txt:
a1,a2,a3,a4
b1,,b3,b4
,,c3,
d1,d2,d3,
Running the following awk results in empty fields being periods.
awk -F',' 'function clean() {
for(i = 1; i <= NF; i++) { if($i==""){$i="."}; }
}
BEGIN {OFS=","}
{clean(); print;}' test.txt
Example output:
a1,a2,a3,a4
b1,.,b3,b4
.,.,c3,.
d1,d2,d3,.
Let's start by cleaning up your script. Replace the whole thing with just one simple awk command:
awk -v file_name="$file_name" '
BEGIN {OFS="\t"; print 1, 1, 1, 1 ORS 1, 1, 1, 3 > (file_name ".del")}
/DIF/ {print $4, $5, $20, $10, $11, $22, "Null" > (file_name "." ($7==$13?"inv_":"") "fus")}
/DEL/ {print $4, $5, $12, 2 > (file_name ".del")}
' "$file"
Now, update your question with sample input and expected output that captures what else you need it to do.

awk match and merge two files on basis of key values

I have two files in which $3,$4 = $3,$2.
file1:
1211,A2,ittp,1,IPSG,a2,PA,3000,3000
1311,A4,iztv,1,IPSG,a4,PA,240,250
1411,B4,iztq,0,IPSG,b4,PA,230,250
file2:
TP,0,nttp,0.865556,0.866667
TP,1,ittp,50.7956,50.65
TP,1,iztv,5.42444,13.8467
TP,0,iztq,645.194,490.609
I want to merge these files and print a new file like if file1 $3,$4 = file2 $3,$2 then print merged file like
TP,1211,A2,ittp,1,IPSG,a2,PA,3000,3000,0.865556,0.866667
TP,1311,A4,iztv,1,IPSG,a4,PA,240,250,50.7956,50.65
TP,1411,B4,iztq,0,IPSG,b4,PA,230,250,5.42444,13.8467
BOTH THE FILES ARE CSV FILES.
I tried using awk but I'm not getting the desired output. It's printing only file1.
$ awk -F, 'NR==FNR{a[$3,$4]=$3$2;next}{print $1, $2, $3, $4, $5, $6, $7, $8, $9, $10 a[$1] }' OFS=, 1.csv 2.csv
awk -F, 'BEGIN {OFS=",";}
NR == FNR {a[$3,$4] = $0;}
NR != FNR && a[$3,$2] {print $1, a[$3,$2], $4, $5;}' 1.csv 2.csv
One way with awk:
awk 'NR==FNR{a[$4,$3]=$0;next}($2,$3) in a{print $1,a[$2,$3],$4,$5}' FS=, OFS=, f1 f2
TP,1211,A2,ittp,1,IPSG,a2,PA,3000,3000,50.7956,50.65
TP,1311,A4,iztv,1,IPSG,a4,PA,240,250,5.42444,13.8467
TP,1411,B4,iztq,0,IPSG,b4,PA,230,250,645.194,490.609
Using Join
If i1 and i2 are the input files
cat i1.txt | awk -F',' '{print $3 "-" $4 "," $1 "," $2 "," $5 "," $6 "," $7 "," $8 "," $9}' | sort > s1.txt
cat i2.txt | awk -F',' '{print $3 "-" $2 "," $1 "," $4 "," $5 }' | sort > s2.txt
join -t',' s1.txt s2.txt | tr '-' ',' > t12.txt
cat t12.txt | awk -F ',' '{print $10 "," $3 "," $4 "," $1 "," $2 "," $5 "," $6 "," $7 "," $8 "," $9 "," $11 "," $12 }'

how to pipe into awk script

I have this awk script:
#!/usr/bin/awk -f
BEGIN {IGNORECASE=1}
/nVidia/ {inner=1;pci=$1}
/(corr|fatal)err\-/ {if (inner) print pci, $1, $2, $3, $4, $5, $6, $7}
$0=="" {inner=0}
is there a syntax to always pipe sudo lspci -vvv to this script? I'm having to type sudo lspci -vvv|./checkpci each time I run the script. I know I could create a second script to launch the first script, but I think that is messy and would like to know the proper way to do so.
as an aside, I'm having some issues with my graphics card crashing and have seen the UncorrErr flag on some of the devices, does anyone have a reference as to what this means or how to troubleshoot further? right now I'm just going to run this script periodically to see when the errors show up in lspci to see if there is a time correlation.
This should work for you:
#!/usr/bin/awk -f
BEGIN {
IGNORECASE = 1
cmd = "sudo lspci -vvv"
while ((cmd | getline) > 0) {
if ($0 ~ /nVidia/) {inner = 1; pci = $1}
if ($0 ~ /(corr|fatal)err\-/) {if (inner) print pci, $1, $2, $3, $4, $5, $6, $7}
if ($0 == "") {inner = 0}
}
close(cmd)
}
I would change your awk script into a shell script:
#!/bin/sh
sudo lspci -vvv | /usr/bin/awk '
BEGIN {IGNORECASE=1}
/nVidia/ {inner=1;pci=$1}
/(corr|fatal)err\-/ {if (inner) print pci, $1, $2, $3, $4, $5, $6, $7}
$0=="" {inner=0}
'

Resources