awk not printing output to secondary file, syntax error? - awk

More with my radio logs... So far the work I have completed is great, push notifications are going out perfectly, too well in fact. I am getting bombarded with every accidental connection. I want to filter the log to only send notifications if the mic is keyed up longer than 1.5 seconds (the 4th field), cutting the notifications down to real communication only. I am trying to filter the original "completelog.txt" file over to the "filteredlog.txt" file. The original looks like this:
W7MIT,TG 91,4601149,0.5,0,0.00
W7MIT,TG 91,4601149,0.8,0,0.00
VA3GJB,TG 91,4601149,1.2,0,0.00
G0IOR,TG 91,2345614,11.6,0,0.00
G0IOR,TG 91,2345614,10.6,0,0.00
G4NHP,TG 91,2345614,6.2,2,0.00
GM0TKC,TG 91,2345614,0.5,0,0.00
EA8CTB,TG 91,2345614,2.3,0,0.00
EA8CTB,TG 91,2345614,1.6,0,0.00
GM1RCP,TG 91,2345614,0.5,12,0.00
The code I have tried using is here:
#!/bin/bash
awk -v x=1.5 '$4 >= x' completelog.txt >> filteredlog.txt
Then I tried not appending (I think)
#!/bin/bash
awk -v x=1.5 '$4 >= x' completelog.txt > filteredlog.txt
Since neither worked I added sudo (don't think that is needed)
#!/bin/bash
sudo awk -v x=1.5 '$4 >= x' completelog.txt >> filteredlog.txt
And again not appending (still thinking that is what that means).
#!/bin/bash
sudo awk -v x=1.5 '$4 >= x' completelog.txt > filteredlog.txt
Then I just started guessing random things.
awk -v x=1.5 '$4 >= x' completelog.txt
And again...
awk '$4>=1.5{print}' completelog.txt
All to no avail. I did get few permission errors even though the files are chmoded and even tried with sudo. Please tell me what am I doing wrong?

The issue is that you aren't setting the delimiter (Field Separator) in awk so it's expecting whitespace delimitation by default. Instead:
awk -F"," -v x=1.5 '$4 >= x' completelog.txt >> filteredlog.txt
You can also specify this in the BEGIN block of the awk script itself by setting the FS built-in variable:
awk -v x=1.5 'BEGIN{OFS=FS=","}$4>=x' completelog.txt >> filteredlog.txt
That sets the Field Separator FS and the Output Field Separator OFS to a comma.

(not an answer, an extended comment)
The sudo [command ...] > file redirection is kind of misleading: you run the command with sudo privs, but the file redirection is done with your privs. This is because the shell processes redirections before processing the actual command.
Two workarounds:
use tee with sudo privs:
some command with args | sudo tee -a privileged_file
This runs the command as you, but appends to the file as sudo.
wrap everything in a shell with sudo privs:
sudo sh -c 'some command with args >> privileged_file'

Permission error noticed after posting, but the comma delimiter was also a great catch, thank you both.
pi-star#pi-star(rw):~$ awk -F"," '$4>=1.6{print}' completelog.txt >
filteredlog.txt
-bash: filteredlog.txt: Permission denied
pi-star#pi-star(rw):~$ touch filteredlog.txt
touch: cannot touch ‘filteredlog.txt’: Permission denied
pi-star#pi-star(rw):~$ ls -l filteredlog.txt
-rwxr-xr-x 1 root root 0 Jun 10 08:09 filteredlog.txt
pi-star#pi-star(rw):~$ sudo chmod 777 filteredlog.txt
pi-star#pi-star(rw):~$ ls -l filteredlog.txt
-rwxrwxrwx 1 root root 0 Jun 10 08:09 filteredlog.txt
pi-star#pi-star(rw):~$ awk -F"," '$4>=1.6{print}' completelog.txt >
filteredlog.txt
pi-star#pi-star(rw):~$ tail -f -n2 filteredlog.txt
PD2RAL,TG 91,2042416,6.7,1,0.00
N1AJW,TG 91,2042416,2.2,2,6.70

Related

Adding hashtag to files

I have a awk program add_hashtag.awk
BEGIN{printf("#")}1
and a bash program
for file in *.asc; do awk -f add_hashtag.awk "$file" > "$file"_in; done
that add hashtag into file. It works, however, I would like to get files with same names. When I run
for file in *.asc; do awk -f add_hashtag.awk "$file" > "$file"; done
I get files only with #.
How to do that? Thank you
Could you please try following.
for file in *.asc; do awk -f add_hashtag.awk "$file" > "temp_file" && mv "temp_file" "$file"; done
I am going with approach where creating a temp_file for output and later renaming it to Input_file so that there will not be any danger of losing or truncating actual Input_file. Also it will not rename temp_file to actual Input_file until/unless awk command is a success(with use of &&)
With gawk 4.1.0 version or so try(haven't tested it since no samples were given):
awk -i inplace -f add_hashtag.awk *.asc
OR in case you want to inplace edit files along with taking their backup:
awk -i inplace -v INPLACE_SUFFIX=.backup -f add_hashtag.awk *.asc

How to insert argument in awk script?

I'm writing a shell script which shut down some services and trying to get its pid by using the following awk script.
However, this awk script can't get pid. What's wrong with that?
ps -ef | awk -v port_no=10080 '/[m]ilk.*port=port_no/{print $2}'
The result of ps -ef is like this:
username 13155 27705 0 16:06 pts/2 00:00:00 /home/username/.rbenv/versions/2.3.6/bin/ruby /home/username/.rbenv/versions/2.3.6/bin/milk web --no-browser --host=example.com --port=10080
This process is working with a different port argument as well, so I want to kill the process only working on port=10080.
The awk script below works fine, but when I specify the port no using awk -v like the above, it doesn't work well.
ps -ef | awk '/[m]ilk.*port=10080/{print $2}'
awk version: GNU Awk 4.0.2
The syntax for pattern matching with /../ does not work with variables in the regular expression. You need to use the ~ syntax for it.
awk -v port_no=10080 '$0 ~ "[m]ilk.*port="port_no{print $2}'
If you notice the regex carefully, the regex string on the r.h.s of ~ is under the double-quotes ".." except the variable name holding the port number which shouldn't be under quotes, for the expansion to happen.
This task is easily accomplished using pgrep:
$ pgrep -f '[m]ilk.*port=10080'
Have a look at man pgrep for details.

Awk losing posix mode under sudo

This started as an obscure problem with RPM scriptlets occasionally failing on awk. I narrowed it down to the following: The scriptlets use a GNU extension: length(array) construct, not supported when running in the posix mode. OK so far. What I don't understand is how running awk under sudo changes the posix compliance behavior. Here is a simple awk script that should run in the GNU mode, and should fail in posix mode.
$ cat ./try
/bin/awk 'BEGIN{x[1]=foo;x[2]=bar;print length(x);}'
$ /bin/awk --version | grep Awk
GNU Awk 4.0.2
$ id
uid=0(root) gid=0(root) groups=0(root)
$ /bin/sh ./try
awk: cmd. line:1: fatal: length: received array argument
$ sudo /bin/sh ./try
2
$
What is the underlying mechanism that changes the awk behavior?
Awk (really gawk under linux) is being controlled by the POSIXLY_CORRECT environment variable, which was occasionally being inherited from the original user's environment. The installation in question must be run by root, but at times the admin would become root with "su" which keeps the environment, thus keeping his POSIXLY_CORRECT, forcing gawk into a posix mode, and failing the GNU length(array) extension. At other times the admin would run "sudo" or "su -" to become root, start with root's clean environment and successfully run the extended gawk functionality.

Execute a command in the re-verse order of ids present in a file

I am running the following command using awk on file.txt ,currently its running the command on the ids present in file.txt from top to bottom..i want the commmand to be run in the reverse order for the ids present in file.txt..any inputs on how we can do this?
git command $(awk '{print $1}' file.txt)
file.txt contains.
97a65fd1d1b3b8055edef75e060738fed8b31d3
fb8df67ceff40b4fc078ced31110d7a42e407f16
a0631ce8a9a10391ac4dc377cd79d1adf1f3f3e2
.....
If you aren't bound to using awk then tail with the -r (for reverse) argument will do the trick...
myFile.txt
97a65fd1d1b3b8055edef75e060738fed8b31d3
fb8df67ceff40b4fc078ced31110d7a42e407f16
a0631ce8a9a10391ac4dc377cd79d1adf1f3f3e2
Now to print it in reverse...
$ tail -r myFile.txt
a0631ce8a9a10391ac4dc377cd79d1adf1f3f3e2
fb8df67ceff40b4fc078ced31110d7a42e407f16
97a65fd1d1b3b8055edef75e060738fed8b31d3
EDIT:
To output this to a file simply redirect it out...
$ tail -r myFile.txt > newFile.txt
EDIT:
Want to write to the same file? No problem!
tail -r myFile.txt > temp.txt; cat temp.txt > myFile.txt; rm temp.txt;
For some reason when I redirected tail -r to the same file it came back blank, this workaround avoids that issue by writing to a temporary "buffer" file.
To reverse the lines in a file using awk, use
awk '{a[i++]=$0} END {for (j=i-1; j>=0;) print a[j--] }' file
use $1 instead of $0 above to operate on the first field only instead of the whole line.

piping to awk hangs

I am trying to pipe tshark output to awk. The tshark command works fine on its own, and when piped to other programs such as cat, it works fine (real time printing of output). However, when piped to awk, it hangs and nothing happens.
sudo tshark -i eth0 -l -f "tcp" -R 'http.request.method=="GET"' -T fields -e ip.src -e ip.dst -e
tcp.srcport -e tcp.dstport -e tcp.seq -e tcp.ack | awk '{printf("mz -A %s -B %s -tcp \"s=%s sp=%s
dp=%s\"\n", $2, $1, $5, $4, $3)}'
Here is a simplier version:
sudo tshark -i eth0 -f "tcp" -R 'http.request.method=="GET"' | awk '{print $0}'
And to compare, the following works fine (although is not very useful):
sudo tshark -i eth0 -f "tcp" -R 'http.request.method=="GET"' | cat
Thanks in advance.
I had the same problem.
I have found some partial "solutions" that are not completely portable.
Some of them point to use the fflush() or flush() awk functions or -W interactive option
http://mywiki.wooledge.org/BashFAQ/009
I tried both and none works. So awk is not the appropriate command at all.
A few of them suggest to use gawk but it neither does the trick for me.
cut command has the same problem.
My solution: In my case I just needed to put --line-buffered in GREP and not touching awk command but in your case I would try:
sed -u
with the proper regular expression. For example:
sed -u 's_\(.*\) \(.*\) \(.*\) DIFF: \(.*\)_\3 \4_'
This expression gives you the 3rd and 4th columns separate by TAB (written with ctrl+v and TAB combination). With -u option you get unbuffered output and also you have -l option that gives you line buffered output.
I hope you find this answer useful although is late
Per our previous messages in comments, maybe it will work to force closing the input and emitting a linefeed.
sudo tshark -i eth0 -f "tcp" -R 'http.request.method=="GET"' ...... \
| {
awk '{print $0}'
printf "\n"
}
Note, no pipe between awk and printf.
I hope this helps.
I found the solution here https://superuser.com/questions/742238/piping-tail-f-into-awk (by John1024).
It says:
"You don't see it in real time because, for purposes of efficiency, pipes are buffered. tail -f has to fill up the buffer, typically 4 kB, before the output is passed to awk."
The proposed solutions is to use "unbuffer" or "stdbuf -o0" commands to disable buffering. It worked for me like this:
stdbuf -o0 tshark -i ens192 -f "ip" | awk '{print $0}'