I have a report xyz.rpt in the below format
# ajsh askj sdjh 54 12
# jhgj 765 2839
kjsd sdh sdsdf sdffsdf sdff
5464 765 67 65 76
2356 423 34 45 34
and so on
I want to print first 2 header line also along with the output of awk command.
awk '{if ( $5 < 65 ) print}' > aaa.rpt
One awk idea:
awk '
FNR<=2 # print 1st 2 lines
FNR>2 && $5+0==$5 && $5<65 # print lines where $5 is numeric and $5 < 65
' xyz.rpt
Or as a one-liner:
awk 'FNR<=2; FNR>2 && $5+0==$5 && $5 < 65' xyz.rpt
This generates:
ajsh askj sdjh 54 12
jhgj 765 2839
2356 423 34 45 34
not as elegant as i hoped
nawk '($5==+$(5*(+$5<=4^3)))+(3>FNR)'
ajsh askj sdjh 54 12
jhgj 765 2839
2356 423 34 45 34
$ awk 'NR<=2 || ($5+0==$5 && $5<65)' file
My solution would be:
awk 'BEGIN { for(i=0;i<2;i++) {getline; print;}}$5<65{print}' input
The BEGIN block is executed at the start. getline reads a line, which gets outputed.
$5<65 In stead of the if construction it's better to use a pattern.
Related
I have a file with multiple columns:
$ cat file.txt
a bc 34 67
t gh 68 -34
f jh -9 76
h in -66 -14
and so on
I am trying to extract when both columns are negative; when both are positive then subtract the two columns based on which value is greater; and if either column negative then add both the columns
For both negative its quite easy:
less file.txt | egrep -i "\-.*\-" | less
Expected Output:
h in -66 -14
For both positive I tried the following to no avail:
less file.txt | egrep -iv "\-.*\-" | awk '($3>$4 {print $0,($3-$4)}) || ($4>$3 {print $0,($4-$3)})' | less
Expected Output:
a bc 34 67 33
For either negative,
less file.txt | egrep -iv "\-.*\-" | awk '($3<0||$4<0) {print $0,($3+$4)}' | less
Expected Output:
t gh 68 -34 34
f jh -9 76 67
I am seeing this error:
awk: cmd. line:1: (FILENAME=- FNR=3208) fatal: print to "standard output" failed (Broken pipe)
egrep: write error
I know its a basic thing to do, any help would be appreciated!
One awk idea:
awk '
$3<0 && $4<0 { print $0 ; next }
$3>0 && $4>0 { print $0, ($3>=$4 ? $3-$4 : $4-$3); next }
{ print $0, $3+$4 }
' file.txt
NOTE: may need to be tweaked if $3==0 and/or $4==0 ... depends on OP's requirements for this scenario
This generates:
a bc 34 67 33
t gh 68 -34 34
f jh -9 76 67
h in -66 -14
Another awk implementation:
awk '
function abs(x) {
if (x < 0) x = -x
return x
}
$3 >= 0 || $4 >= 0 {$(NF+1) = abs(abs($3) - abs($4))}
{print}
' file.txt
a bc 34 67 33
t gh 68 -34 34
f jh -9 76 67
h in -66 -14
If you wanted to do this in plain bash:
abs() { echo $(($1 < 0 ? -($1) : $1)); }
while read -ra fields; do
a=${fields[2]}
b=${fields[3]}
if ((a >= 0 || b >= 0)); then
fields+=($(abs $(($(abs $a) - $(abs $b)))))
fi
echo "${fields[*]}"
done < file.txt
I have a huge file which i am reading through awk , using awk i am calculating the sum of values on that file.
Below is the file format i have :
18/11/13 00:00:50 585 17353 296883 666
18/11/13 00:01:50 965 26536 216201 558
18/11/13 00:02:50 990 38685 390537 768
18/11/13 00:03:50 1004 22435 377633 404
18/11/13 00:04:50 709 15754 161435 12062
18/11/13 00:05:50 96 7084 403551 0
18/11/13 00:06:50 107 14588 504683 597
18/11/13 00:07:50 115 27562 457555 814
awk '{sum+=$4; ++n} END {print " Tot="n," Avg="sum/n}' filename
Now i thin i want to skip 2 rows after we read a row from the file.
for your comment under your question, you just need to skip line2 and 3:
awk 'NR==1||NR>3{sum+=$4; ++n} END {print " Tot="n," Avg="sum/n}' filename
Consider a file "test" containing following data:
REG NO: 123
20
24
REG NO: 124
30
70
Need to print the following:
123 20
123 24
124 30
124 70
The value need to be printed from different fields. And content of the heding column (regno ie 123,124) need to repeated for their marks.
In awk:
$ awk 'NF>1 {p=$NF;next} {print p, $1}' file
123 20
123 24
124 30
124 70
Explained:
$ awk '
NF>1 { # when a record has more than one field
p=$NF # store the last field to p var
next # proceed to next record
}
{
print p, $1 # otherwise output the p and the value on the record
}' file
I have a tab delimited text file like
file 1
x1 23 47 59
x2 58 23 12
x3 39 30 11
...
x21909 020
and a simple list of values like
file 2
x1
x34
x56
x123
..
x9876
I'd like to take all of the rows in file 1 beginning with the values in file 2 and move them into a file 3, such that..
file 3
x1 23 47 69
x34 38 309 20
x56 49 201 10
x123 39 30 10
..
x9876 48 309 123
I've tried using the grep command but I'm not sure how to do it with a long list of values in file 2, and how to make it take the entire row. Is there a simple shell command which could do this?
With tabs as the delimiter, this should work:
for i in `cat file2`; do grep -P "^$i\t" file1; done
And with spaces as the delimiter, something like this should work:
for i in `cat file2`; do grep "^$i " file1; done
Cheers.
awk 'NR==FNR{a[$1]=$0;next} {print a[$1]}' file1 file2
if the first field values are distinct from the rest of the fields, grep fits the bill
grep -Ff file2 file1
I have this input below:
IDNO H1 H2 H3 HT Q1 Q2 Q3 Q4 Q5 M1 M2 EXAM
OUT OF 100 100 150 350 30 30 30 30 30 100 150 400
1434 22 95 135 252 15 20 12 18 14 45 121 245
1546 99 102 140 341 15 17 14 15 23 91 150 325
2352 93 93 145 331 14 17 23 14 10 81 101 260
(et cetera)
H1 H2 H3 HT Q1 Q2 Q3 Q4 Q5 M1 M2 EXAM
OUT OF 100 100 150 350 30 30 30 30 30 100 150 400
I need to use write a unix script to use the awk function to dynamically find any column that is entered in and have it displayed to the screen. I have successfully awked specific columns, but I cant seem to figure out how to make it change based on different columns. My instructor will simply pick a column for test data and my program needs to find that column.
what I was trying was something like:
#!/bin/sh
awk {'print $(I dont know what goes here)'} testdata.txt
EDIT: Sorry i should have been more specific, he is entering in the header name as the input. for example "H3". Then it needs to awk that.
I think you are just looking for:
#!/bin/sh
awk 'NR==1{ for( i = 1; i <= NF; i++ ) if( $i == header ) col=i }
{ print $col }' header=${1?No header entered} testdata.txt
This makes no attempt to deal with a column header that does not appear
in the input. (Left as an exercise for the reader.)
Well, you question is quite diffuse and in principle you want someone else write your awk script... You should check man pages for awk, they are quite descriptive.
my 2 cent wort, as an example would be (for the row) :
myscript.sh:
#/bin/sh
cat $1 | awk -v a=$2 -v b=$3 '{if ($(a)==b){print $0}}';
if you just want a column, well,
#/bin/sh
cat $1 | awk -v a=$2 '{print $(a)}';
Your input would be :
myscript.sh file_of_data col_num
Again, reiterating: Please study man pages of awk. Also please when asking question present what you have tried (code) and errors (logs). This will make people more ready to help you.
Your line format has a lot of variation (in the number of fields). That said, what about something like this:
echo "Which column name?"
read column
case $column in
(H1) N=2;;
(H2) N=3;;
(H3) N=4;;
...
(*) echo "Please try again"; exit 1;;
esac
awk -v N=$N '{print $N}' testdata.txt