How to format the out put from database in shell scripting - shell

I have written shell scripting and extracting records from database. And below is my result in xyz.txt file.
NAME
COUNT(*)
Ben 7
Tim 4
BPNAME
COUNT(*)
Mark 7
Jhon 4
But how do i format it as below.? So i can send email to display the same.
NAME COUNT
Ben 7
Tim 4
Mark 7
Jhon 4

awk solution:
awk 'BEGIN{ print "NAME","COUNT" }!/NAME|COUNT/{ print $1,$2 }' xyz.txt | column -t
The output:
NAME COUNT
Ben 7
Tim 4
Mark 7
Jhon 4

You can achieve this task with awk, inclusive formatting instead of piping to column -t like already suggested.
In the BEGIN section of awk you can always print print a header. For formatted printing you can always switch from print to printf.
After the BEGIN section have been executed, printf 1st and 2nd column only if there is no (!) pattern like NAME or (|) COUNT.
$ awk 'BEGIN{ printf "NAME\tCOUNT\n" } !/NAME|COUNT/ { printf "%s\t%s\n", $1,$2 }' file

Related

awk print the last row of file failed

$cat file
1
2
3
4
5
6
7
8
9
0
I want to print the value of last row.
$awk '{print $NR}' file
1
Why the output is not 0?
Unlike sed, awk does not have a way to specify the last line. A work-around is:
$ awk '{line=$0} END{print line}' file
0
Discussion
Let's look at your command at see what it actually does. Consider this test file:
$ cat testfile
a b c
A B C
i ii iii
Now, let's run your command:
$ awk '{print $NR}' testfile
a
B
iii
As you can see, print $NR prints the diagonal. In other words, on line number NR, it prints field number NR. So, on the first line, NR=1, the command print $NR prints the first field. On the second line, NR=2, the command print $NR prints the second field. And so on.
Use following code, which will print the last line of any Input_file. Here END section is the out of the box awk keyword which is used to execute the commands/statements after main section. So I am simply printing the line in END section which will print the last line.
awk 'END{print $0}' Input_file
OR
awk 'END{print}' Input_file

Count of unique words from one column of a file in shell

I was trying find out the count of unique words from one column of a file, and the words themselves, using a shell script. Here's what I was doing. Input file contains (filename: gnc.txt, new line after city name):
Male,Tyrus,Seattle
Male,Sam,Seattle
Male,Meha,Seattle
Male,John,Seattle
Male,Sam,Beijing
Male,Meha,Paris
Male,Meha,Berlin
As a first step I found out the number of unique names, which is 4 using below shell commands.
awk -F\, '{ if(!a[$2]) cnt++;a[$2]++;next}END{ print cnt }' gnc.txt
As a next step I want to get the list of unique names: i.e. Tyrus, Sam, Meha and John
Can someone help me in this on how to alter the above command?
Using this awk:
awk -F, '{c[$2]++} END{for (i in c) print i, c[i]}' file
Tyrus 1
Sam 2
John 1
Meha 3
You can also use this:
cut -d',' -f2 file | sort | uniq -c
1 John
3 Meha
2 Sam
1 Tyrus

awk: print first line of file before reading lines

How would I go about printing the first line of given input before I start stepping through each of the lines with awk?
Say I wanted to run the command ps aux and return the column headings and a particular pattern I'm searching for. In the past I've done this:
ps aux | ggrep -Pi 'CPU|foo'
Where CPU is a value I know will be in the first line of input as it's one of the column headings and foo is the particular pattern I'm actually searching for.
I found an awk pattern that will pull the first line:
awk 'NR > 1 { exit }; 1'
Which makes sense, but I can't seem to figure out how to fire this before I do my pattern matching on the rest of the input. I thought I could put it in the BEGIN section of the awk command but that doesn't seem to work.
Any suggestions?
Use the following awk script:
ps aux | awk 'NR == 1 || /PATTERN/'
it prints the current line either if it is the first line in output or if it contains the pattern.
Btw, the same result could be achieved using sed:
ps aux | sed -n '1p;/PATTERN/p'
If you want to read in the first line in the BEGIN action, you can read it in with getline, process it, and discard that line before moving on to the rest of your awk command. This is "stepping in", but may be helpful if you're parsing a header or something first.
#input.txt
Name City
Megan Detroit
Jackson Phoenix
Pablo Charlotte
awk 'BEGIN { getline; col1=$1; col2=$2; } { print col1, $1; print col2, $2 }' input.txt
# output
Name Megan
City Detroit
Name Jackson
City Phoenix
Name Pablo
City Charlotte
Explaining awk BEGIN
I thought I could put it in the BEGIN section ...
In awk, you can have more than one BEGIN clause. These are executed in order before awk starts to read from stdin.

Extracting field from last row of given table using sed

I would like to write a bash script to extract a field in the last row of a table. I will illustrate by example. I have a text file containing tables with space delimited fields like ...
Table 1 (foobar)
num flag name comments
1 ON Frank this guy is frank
2 OFF Sarah she is tall
3 ON Ahmed who knows him
Table 2 (foobar)
num flag name comments
1 ON Mike he is short
2 OFF Ahmed his name is listed twice
I want to extract the first field in the last row of Table1, which is 3. Ideally I would like to be able to use any given table's title to do this. There are guaranteed carriage returns between each table. What would be the best way to accomplish this, preferably using sed and grep?
Awk is perfect for this, print the first field in the last row for each record:
$ awk '!$1{print a}{a=$1}END{print a}' file
3
2
Just from the first record:
$ awk '!$1{print a;exit}{a=$1}' file
3
Edit:
For a given table title:
$ awk -v t="Table 1" '$0~t{f=1}!$1&&f{print a;f=0}{a=$1}END{if (f) print a}' file
3
$ awk -v t="Table 2" '$0~t{f=1}!$1&&f{print a;f=0}{a=$1}END{if (f) print a}' file
2
This sed line seems to work for your sample.
table='Table 2'
sed -n "/$table"'/{n;n;:next;h;n;/^$/b last;$b last;b next;:last;g;s/^\s*\(\S*\).*/\1/p;}' file
Explanation: When we find a line matching the table name in $table, we skip that line, and the next (the field labels). Starting at :next we push the current line into the hold space, get the next line and see if it is blank or the end of the file, if not we go back to :next, push the current line into hold and get another. If it is blank or EOF, we skip to :last, pull the hold space (the last line of the table) into pattern space, chop out all but the first field and print it.
Just read each block as a record with each line as a field and then print the first sub-field of the last field of whichever record you care about:
$ awk -v RS= -F'\n' '/^Table 1/{split($NF,a," "); print a[1]}' file
3
$ awk -v RS= -F'\n' '/^Table 2/{split($NF,a," "); print a[1]}' file
2
Better tool to that is awk!
Here is a kind legible code:
awk '{
if(NR==1) {
row=$0;
next;
}
if($0=="") {
$0=row;
print $1;
} else {
row=$0;
}
} END {
if(row!="") {
$0=row;
print $1;
}
}' input.txt

Computing differences between columns of tab delimited file

I have a tab delimited file of 4 columns and n number of rows.
I want to find the difference in values present in column 3 and 2 and want to store them in another file.
This is what I am doing
cat filename | awk '{print $3 - $2}'>difference
and it is not working. How can I improve the code?
Solution:
I was missing the closing single quotation, and my eyes were so tuned to the screen that I couldn't figure it out in 35 lines code what was going wrong...and out of frustration I wrote the question on forum ... and [to complete] the comedy of errors, the syntax I wrote here [in the] question is correct (as it contains both single quotes).
Thank you all for your help.
Set the field separator if you have other whitespace in the lines.
BEGIN {
FS="\t"
}
Try using -F to force the delimiter as tab and enclose your
cat filename | awk -F"\t" '{print $3 - $2}' > difference
Does anyone test before they give their answers/ awk breaks on white space and not just spaces.
I just did this:
awk '{print $3 - $2}' temp.txt
And it works perfectly.
Here's my file:
1 2 7 4
11 12 13 14
1 12 3 4
1 2 3 4
1 2 3 4
And here's my results:
$ awk '{print $3 - $2}' temp.txt
5
1
-9
1
1
$
In fact, I used your command, and got the same results?
Can you explain what's not working for you? What data are you using, and what results are you getting?
Try this:
cat filename | awk -F '^T' '{print $3 - $4}' > difference
where ^T is tab delimiter (get it by pressing Ctrl+V+T)

Resources