shell script inserting "$" into a formatted column and adding new column - shell

Hi guys pardon for my bad English. I manage to display out my data nicely and neatly using column program in the code. But how do i add a "$" in the price column. Secondly how do i add a new column total sum to it and display it with "$". (Price * Sold)
(echo "Title:Author:Price:Quantity:Sold" && cat BookDB.txt) | column -s: -t
Output:
Title Author Price Quantity Sold
The Godfather Mario Puzo 21.50 50 20
The Hobbit J.R.R Tolkien 40.50 50 10
Romeo and Juliet William Shakespeare 102.80 200 100
The Chronicles of Narnia C.S.Lewis 35.90 80 15
Lord of the Flies William Golding 29.80 125 25
Memories of a Geisha Arthur Golden 35.99 120 50

I guess you could do it with awk (line break added before && for readability
(echo "Title:Author:Price:Quantity:Sold:Calculated"
&& awk -F: '{printf ("%s:%s:$%d:%d:%d:%d\n",$1,$2,$3,$4,$5,$3*$5)}' BookDB.txt) | column -s: -t

Related

How to keep the header of the file when filtering using awk [duplicate]

This question already has answers here:
Filter file with awk and keep header in output
(2 answers)
Closed 1 year ago.
I have a file that looks like this with a header. I am just showing the first 8 columns although there are 26 columns.
id Id Study Site CancerType Sex Country unexpected_duplicates
468768 1032 Response Karlburg VN Breast Female Germany
468769 1405 Response Santiago Prostate Male Spain
I want to filter the Cancer type (column 5) by "Breast" using this command which works fine:
awk '($5 == "Breast")' PCA.covar > PCA.covar1
The only problem is my header is not printed and the first line is missing in the output.
So I modified my command to:
awk 'NR==1; NR > 1 ($5 == "Breast")' PCA.covar > PCA.covar1
And I see that while the header is there, it has not filtered by Breast:
id Id Study Site CancerType Sex Country unexpected_duplicates
468768 1032 Response Karlburg VN Breast Female Germany
468769 1405 Response Santiago Prostate Male Spain
68772 RQ56001-9 Response Maastricht Prostate Male Netherlands
This should do it:
awk 'NR==1 || $5 == "Breast"{print}' PCA.covar > PCA.covar1

Uniq a column and print out number of rows in that column

I have a file, with header
name, age, id, address
Smith, 18, 201392, 19 Rand Street, USA
Dan, 19, 029123, 23 Lambert Rd, Australia
Smith, 20, 192837, 61 Apple Rd, UK
Kyle, 25, 245123, 103 Orange Rd, UK
And I'd like to sort out duplicates on names, so the result will be:
Smith, 18, 201392, 19 Rand Street, USA
Dan, 19, 029123, 23 Lambert Rd, Australia
Kyle, 25, 245123, 103 Orange Rd, UK
# prints 3 for 3 unique rows at column name
I've tried sort -u -t, -k1,1 file, awk -F"," '!_[$1]++' file but it doesn't work because I have commas in my address.
Well, you changed the functionality since the OP, but this should get you unique names in your file (considering it's named data), unsorted:
#!/bin/bash
sed "1 d" data | awk -F"," '!_[$1]++ { print $1 }'
If you need to sort, append | sort to the command line above.
And append | wc -l to the command line to count lines.

How can we sum the values group by from file using shell script

I have a file where I have student Roll no, Name, Subject, Obtain Marks and Total Marks data:
10 William English 80 100
10 William Math 50 100
10 William IT 60 100
11 John English 90 100
11 John Math 75 100
11 John IT 85 100
How can i get Group by sum (total obtained marks) of every student in shell Shell? I want this output:
William 190
John 250
i have tried this:
cat student.txt | awk '{sum += $14}END{print sum" "$1}' | sort | uniq -c | sort -nr | head -n 10
This is not working link group by sum.
With one awk command:
awk '{a[$2]+=$4} END {for (i in a) print i,a[i]}' file
Output
William 190
John 250
If you want to sort the output, you can pipe to sort, e.g. descending by numerical second field:
awk '{a[$2]+=$4} END {for (i in a) print i,a[i]}' file | sort -rnk2
or ascending by student name:
awk '{a[$2]+=$4} END {for (i in a) print i,a[i]}' file | sort
You need to use associative array in awk.
Try
awk '{ a[$2]=a[$2]+$4 } END {for (i in a) print i, a[i]}'
a[$2]=a[$2]+$4 Create associate array with $2 as index and sum of values $4 as value
END <-- Process all records
for (i in a) print i, a[i] <-- Print index and value of array
Demo :
$awk '{ a[$2]=a[$2]+$4 } END {for (i in a) print i, a[i]}' temp.txt
William 190
John 250
$cat temp.txt
10 William English 80 100
10 William Math 50 100
10 William IT 60 100
11 John English 90 100
11 John Math 75 100
11 John IT 85 100
$

Comparision of old and files for new updated records and to insert new records in old files

I want to compare a file which comes with new records, to the same structured file which already have records and exists in the server.
Like old file is file1:
SKU PROD NAME CODE PRICE
A001 shirt jm s02 478
B002 jean jn j02 348
C003 mwear mw m02 567
New file which comes with new record is:
SKU PROD NAME CODE PRICE
A001 shirt jm s02 680
m01 mwear mw m02 567
c02 kurta kr k04 677
d12 dr d3 d03 400
Based on the new records, either old records can be updated or new records can be appended after the old records.
I need to write a unix shell sript for the above scenerio. Please help
Look for the different SKUs in the new file first. If a SKU is not found there, get it from the old file.
grep SKU file1.txt > out.txt
cat file1.txt file2.txt |\
grep -v SKU | cut -d" " -f1 | sort | uniq | while read sku
do
grep $sku file2.txt >> out.txt
if [[ $? -eq 1 ]] # If SKU was not in file2.txt
then
grep $sku file1.txt >> out.txt
fi
done
Result:
SKU PROD NAME CODE PRICE
A001 shirt jm s02 680
B002 jean jn j02 348
C003 mwear mw m02 567
c02 kurta kr k04 677
d12 dr d3 d03 400
m01 mwear mw m02 567
Look at the problem in reverse : your new file is basically your newest data. You could simply replace the old with the new, except that there may be some old data that is not in your new file.
So, a lazy way to do this might be to read your old data, and look for stuff that isn't in your new file, and add it if you need to.
Something like this (off the top of my head, couldn't test it)
while read old_data
do
# find the key
sku=$(echo $old_data | cut -d\ -f1)
# Look for key in new data, paste the line if it's not there.
grep sku new_file > /dev/null || echo old_data >> new_file
done < old_file

Combining tab delimited files based on a column value

Suppose I have two tab-delimited files that share a column. Both files have a header line that gives a label to each column. What's an easy way to take the union of the two tables, i.e. take the columns from A and B, but do so according to the value of column K?
for example, table A might be:
employee_id name
123 john
124 mary
and table B might be:
employee_id age
124 18
123 22
then the union based on column 1 of table A ("employee_id") should yield the table:
employee_id name age
123 john 22
124 mary 18
i'd like to do this using Unix utilities, like "cut" etc. how can this be done?
you can use the join utility, but your files need to be sorted first.
join file1 file2
man join for more information
here's a start. I leave you to format the headers as needed
$ awk 'NR>1{a[$1]=a[$1]" "$2}END{for(i in a)print a[i],i}' tableA.txt tableB.txt
age employee_id
john 22 123
mary 18 124
another way
$ join <(sort tableA.txt) <(sort tableB.txt)
123 john 22
124 mary 18
employee_id name age
experiment with the join options when needed (see info page or man page)
Try:
paste file1 file2 > file3

Resources