How to apply a filter on many columns by `awk` - awk

I want to apply a filter to every 5th column in a file by using awk and print the entire line if all conditions are met on the specified columns. How can I shorten this code?
awk -F "\t" '{if ($5>=10 && $10>=10 && $15>=10 && $20>=10 && $25>=10 && $30>=10 && $35>=10 && $40>=10 && $45>=10 && $50>=10 && $55>=10 && $60>=10 && $65>=10 && $70>=10 && $75>=10 && $80>=10 && $85>=10 && $90>=10 && $95>=10 && $100>=10 && $105>=10 && $110>=10 && $115>=10 && $120>=10 && $125>=10 && $130>=10 && $135>=10 && $140>=10 && $145>=10 && $150>=10 && $155>=10 && $160>=10 && $165>=10 && $170>=10 && $175>=10 && $180>=10 && $185>=10 && $190>=10 && $195>=10 && $200>=10 && $205>=10 && $210>=10 && $215>=10 && $220>=10 && $225>=10 && $230>=10 && $235>=10 && $240>=10 && $245>=10 && $250>=10 && $255>=10 && $260>=10 && $265>=10 && $270>=10 && $275>=10 && $280>=10 && $285>=10 && $290>=10 && $295>=10 && $300>=10 && $305>=10 && $310>=10 && $315>=10 && $320>=10 && $325>=10 && $330>=10 && $335>=10 && $340>=10 && $345>=10 && $350>=10 && $355>=10 && $360>=10 && $365>=10 && $370>=10 && $375>=10 && $380>=10 && $385>=10 && $390>=10) print}' file

You can use a for loop to iterate a column index with a step of 5, and skip to the next record if any of the columns at such indices is less than 10:
awk -F "\t" '{for(i=5;i<=NF;i+=5)if($i<10)next;print}' file

Looping and checking every 5th field as in the other answers is the correct approach but the conditional requires all instances to pass the condition to be satisfied.
Therefore, within the loop, keep track of satisfied conditions with a variable (in my example fail). The first condition failure sets the variable to indicate failure and breaks from the loop. The print statement is executed only if none of the conditions failed:
awk '{for(i=5;i<=NF;i+=5)if($i<10){fail="fail";break;} if (fail != "fail") print }' file.txt
Untested as I'm not clear as to what you want to print, the line or just each fifth element (and that's not part of the question). Also I left out the field-separator reset as I don't think it is needed.

You can iterate all fields
awk '{a=1; for (i =1 ; i<= NF ; ++i) if ( i%5==0 ) a=a&&$i>10; if (a) print file
Edit: All 5th fields greater than 10

Related

awk compare adjacent lines and print based on if statements

I have one file with multiple lines (reads from a genome) and they are sorted (based on their locations). Now I want to loop over these lines and if multiple lines have the same ID (column 4), I want to keep either keep the first, if column 3 is a plus or the last, if column three is a minus. This is m code but it seems like my variable (lastID) is not properly updated after each line.
Tips are much appreciated.
awk 'BEGIN {lastline=""; lastID=""}
{if ($lastline != "" && $4 != $lastID)
{print $lastline; lastline=""};
if ($3 == "+" && $4 != $lastID)
{print $0; lastline=""}
else if ($3 == "+" && $4 == $lastID)
{lastli=""}
else if ($3 == "-")
{lastline=$0};
lastID=$4
}' file
To access the value of a variable in awk you just use the name of the variable, just like in C and most other Algol-based languages. You don't stick a $ in front of it like you would with shell. Try changing:
$lastline != "" && $4 != $lastID
to:
lastline != "" && $4 != lastID
etc.
This might be what you're trying to do (your BEGIN section was doing nothing useful so I just removed it):
awk '
(lastline != "") && ($4 != lastID) {
print lastline
lastline=""
}
$3 == "+" {
if ($4 == lastID) {
lastli=""
}
else {
print $0
lastline=""
}
}
$3 == "-" {
lastline=$0
}
{ lastID=$4 }
' file
When formatted sensibly like that you can see that lastli is never used anywhere except where it's set to "" so that's probably a bug - maybe it's supposed to lastline in which case it can be made common rather than being set in both the if and else legs?
you may want to utilize awk's own condition{statement} structure. Note that code layout is not universally accepted but I find it easier to read for short statements.
$ awk '$lastline!="" && $4 != $lastID {print lastline; lastline=""}
$3=="+" && $4 != $lastID {print; lastline=""}
$3=="+" && $4 == $lastID {lastli=""}
$3=="-" {lastline=$0}
{lastID=$4}' file

Seo url doens't work with homepage in OpenCart 3

I've enabled the option (Use SEO URLs) in settings (Opencart 3). All links such as contact, about, etc are working, except the homepage!
I have added this to the SEO URL page:
Query: common/home
Keyword: home
But it still appears as: index.php?route=common/home
How can I fix that?
I hope it will help you as
Please make changes in catalog/controller/startup/seo_url.php
if `(($data['route'] == 'product/product' && $key == 'product_id') ||
(($data['route'] == 'product/manufacturer/info' ||
$data['route'] == 'product/product') && $key == 'manufacturer_id') ||
($data['route'] == 'information/information' && $key == 'information_id'))
{
to
if (($data['route'] == 'product/product' && $key == 'product_id') ||
(($data['route'] == 'product/manufacturer/info' ||
$data['route'] == 'product/product') && $key == 'manufacturer_id') ||
($data['route'] == 'information/information' && $key == 'information_id') ||
$data['route'] == 'common/home')
{
The problem is the link on the main logo. You can fix this issue by installing the vQmod that is free to download at this link:
https://www.antropy.co.uk/blog/one-quick-opencart-seo-tip-to-avoid-a-duplicate-home-page/

awk with egrep filter unable to return null value with condition

I new in awk, my command as below. When there is no row return need print pass, else print fail. But when there is no value, the pass is unable to display
egrep -v "^\+" /etc/passwd | awk -F: '($1!="root" && $1!="sync" && $1!="shutdown" && $1!="halt" && $3<500 && $7!="/sbin/nologin") {print}' | awk '{if(NR==0||NR<=0||'null') print "pass"; else print "fail"}'
The result should return pass but there is noting print, please advice on this.
consolidate all into one, for example
$ awk -F: '!/^+/ && $1!="root" && ... {f=1; exit}
END {print (f?"fail":"pass")}' /etc/passwd
perhaps better if you set the exit code
$ awk -F: '!/^+/ && $1!="root" && ... {exit 1}' /etc/passwd
This MAY be what you're trying to do:
awk -F: '/^+/ || $1~/^(root|sync|shutdown|halt)$/ || $3>=500 || $7=="/sbin/nologin"{next} {f=1; exit} END{print (f ? "pass" : "fail")}'

fatal: division by zero attempted

when ever I am trying to calculate mean and standard deviation using awk i am getting "awk: fatal: division by zero attempted" error.
my command is
BEGIN{
recvs = 0;
routing_packets = 0;
}
{
state = $1;
layer = $3;
tipe_data = $6;
}
{
if (state == "r" && tipe_data == "tcp" && layer=="AGT") recvs++;
if (state == "s" && layer == "AGT" && tipe_data =="AODV") routing_packets++;
}
END{
printf("##################################################################################\n");
printf("\n");
printf(" Normalized Routing Load = %.3f\n", routing_packets/recvs);
printf("\n");
printf("##################################################################################\n");
}
thanks
Yes, values assigned to recvs and routing_packets variables is zero.
recvs = 0;
routing_packets = 0;
And you are trying to to divide it. That is,
routing_packets/recvs
Which results in,
awk: fatal: division by zero attempted" error
If this if check never succeeds the value of recvs will be equal to 0
if (state == "r" && tipe_data == "tcp" && layer=="AGT") recvs++;
Your program will go on nevertheless and hit this line routing_packets/recvs
You should handle the scenario where recvs is equal to 0 depending on your requirement.
Change this line
printf(" Normalized Routing Load = %.3f\n", routing_packets/recvs);
to
if (recvs)printf(" Normalized Routing Load = %.3f\n", routing_packets/recvs);

awk beginner question about putting some commands in a program file like abc.awk

i need to write this for counting lines between NR= 0-500, 500-1000,1000-1500 etc. till the end, and which start with 1.
awk "{NR<=500 && "/^1/" && sum+=1}; END {print sum}" 1.txt
awk "{NR>500 && NR<=1000 && "/^1/" && sum+=1}; END {print sum}" 1.txt
awk "{NR>1000 && NR<=1500 && "/^1/" && sum+=1}; END {print sum}" 1.txt
.....
here is my question, how can i put these in to a file(*.awk) to run at the same time..
you can try put these commands in a file eg myscript.awk
NR<=500 && /^1/ { sum1 += 1 }
NR>500 && NR<=1000 && /^1/ { sum2 += 1}
NR>1000 && NR<=1500 && /^1/ { sum3+=1 }
END { print sum1,sum2.sum3 }
then run on command line
awk -f myscript.awk 1.txt
you do not need to call awk on the same file 3 times! Its an example of inefficient coding.
you can out a shebang #!/usr/bin/awk -f in the first line of your script only if you want to run it like ./myscript.awk, otherwise , you can leave it out
If you want the script to be pure awk, you need a shebang line with a -f. Make this line one of the file:
#!/usr/bin/awk -f
(or adjust according to the location of the awk you want to use)
One big drawback of that approach is that you must hard code the path of awk in the script. The typical solution to that problem (to use /usr/bin/env) does not work with awk or sed, because they require the -f in the shebang. If you just want to use a shell script wrapper around your awk, you can do something like:
#!/bin/sh
file=${1-1.txt}
awk "{NR<=500 && "/^1/" && sum+=1}; END {print sum}" $file
awk "{NR>500 && NR<=1000 && "/^1/" && sum+=1}; END {print sum}" $file
awk "{NR>1000 && NR<=1500 && "/^1/" && sum+=1}; END {print sum}" $file
Untested, but this should replace all those duplicated lines:
awk '/^1/ {sum++} NR % 500 == 0 {print sum; sum=0} END {print sum}' 1.txt