Print the file according to the pattern - unix

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

Related

AWK apply to all the rows except first few

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.

Replace all "\n" with "," using tr leaves a % at the end of the line, what is it?

Replace all "\n" with "," using tr leaves a % at the end of the line,
I have a file created in vi
name1
name2
name3
When I run the following
cat test.txt| tr "\n" ","
I get name1,name2,name3,%
Could someone explain why it does appear
When I convert it to ascii codes i see
cat test.txt | tr "\n" "," | od -An -t uC
110 97 109 101 49 44 110 97 109 101 50 44 110 97 109 101 51 44
As #shawn mentioned this is just the shell showing there is no new line at the end of the output

group records based on field count unix

I'm having a tough time dealing with a file in Unix. Can someone give me directions on to how to deal with this? Thanks in advance
My file's field count is not consistent. I'm trying to gather all the records which has X number of fields.
when I did a awk check on the file based on the delimiter I found that a big % of my records having 19 fields. So I wanted to quarantine those records and make it a separate file.
file : x_orbit.txt
records : 1000
comma delimeter
cat x_orbit.txt | awk --field-separator=',' '{print NF}' | sort -n| uniq -c
rec col
700 19
50 20
50 21
50 22
50 23
10 24
10 25
10 26
10 27
10 28
9 29
1 31
1 32
1 33
1 35
10 36
27 42
awk '{print > ("out_"(NF==19 ? NF : "other"))}' x_orbit.txt

Moving certain rows of a text file into a new one using shell

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

Dynamically change what is being awked

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

Resources