Filtering /etc/passwd in Unix - bash

I'd like to filter the content of /etc/passwd, only showing the lines for which the value in the third column is greater than 999.
Is there an easy way to do this with a one liner? I'd like to do it without writing a boring for-loop.

This is a simple way to do it:
awk -F: '$3 > 999' /etc/passwd
This uses awk with a field separator of : and instructs it to print the line if the third field is greater than 999. If you want to only print the first field (username) or construct some new lines based on the fields, this is a starting point:
awk -F: '{if ($3 > 999) print "user", $1, "uid", $3}' /etc/passwd

Related

How to call awk from bash with last field as variable

Suppose I have a CSV input file called input.csv:
1,2,3,valueIWantToPrint
3,5,2,valueIWantToPrint
I currently need to print the last element of each row of that input with awk, which is easily accomplished with the field separator and NF variables:
awk -F"," '{print $NF}' input.csv
But now let's say that I want to make the field that I want to print a variable, because later perhaps the input format will change and it will be a different field.
Input file:
1,2,valueIWantToPrint,3
3,5,valueIWantToPrint,2
Script:
FIELD_TO_PRINT=3
awk -F"," -v fieldToPrint=FIELD_TO_PRINT '{print $fieldToPrint}' input.csv
Ok, that was easy. But now to make it as flexible as possible, I would like have the ability to set FIELD_TO_PRINT to the equivalent of NF so that I can print the last value regardless of the number of fields. What I'm after is something like this:
Input:
1,2,3,7,2,5,23,1,3,6,valueIWantToPrint
3,5,2,6,3,valueIWantToPrint
This script doesn't work, but illustrates what I am trying to accomplish:
FIELD_TO_PRINT=NF
awk -F"," -v fieldToPrint=FIELD_TO_PRINT '{print $fieldToPrint}' input.csv
Is there a convenient way to set a variable to mean "the last field in record?" This example is pretty trivial, but ultimately the FIELD_TO_PRINT variable will be put in a separate configuration file, and the awk script will be much larger and more complex. So having a good way to accomplish this will be very useful.
You can use this round-about way:
Negative n means NF:
n=-1
awk -F, -v n="$n" '{print (n<0 ? $NF : $n)}' f.csv
valueIWantToPrint
valueIWantToPrint
and when n > 0 print numbered field:
n=3
awk -F, -v n="$n" '{print (n<0 ? $NF : $n)}' f.csv
3
2
you can use this trick
$ awk -F, -v n=-1 '{print (n<0)?$(NF+n+1):$n}' file
valueIWantToPrint
valueIWantToPrint
assume negative indices start counting from NF backwards, so -2 will mean the penultimate field etc.

Awk, Shell Scripting

I have a file which has the following form:
#id|firstName|lastName|gender|birthday|creationDate|locationIP|browserUsed
111|Arkas|Sarkas|male|1995-09-11|2010-03-17T13:32:10.447+0000|192.248.2.123|Midori
Every field is separated with "|". I am writing a shell script and my goal is to remove the "-" from the fifth field (birthday), in order to make comparisons as if they were numbers.
For example i want the fifth field to be like |19950911|
The only solution I have reached so far, deletes all the "-" from each line which is not what I want using sed.
i would be extremely grateful if you show me a solution to my problem using awk.
If this is a homework writing the complete script will be a disservice. Some hints: the function you should be using is gsub in awk. The fifth field is $5 and you can set the field separator by -F'|' or in BEGIN block as FS="|"
Also, line numbers are in NR variable, to skip first line for example, you can add a condition NR>1
An awk one liner:
awk 'BEGIN { FS="|" } { gsub("-","",$5); print }' infile.txt
To keep "|" as output separator, it is better to define OFS value as "|" :
... | awk 'BEGIN { FS="|"; OFS="|"} {gsub("-","",$5); print $0 }'

awk combine 2 commands for csv file formatting

I have a CSV file which has 4 columns. I want to first:
print the first 10 items of each column
only print the items in the third column
My method is to pipe the first awk command into another but i didnt get exactly what i wanted:
awk 'NR < 10' my_file.csv | awk '{ print $3 }'
The only missing thing was the -F.
awk -F "," 'NR < 10' my_file.csv | awk -F "," '{ print $3 }'
You don't need to run awk twice.
awk -F, 'NR<=10{print $3}'
This prints the third field for every line whose record number (line) is less than or equal to 10.
Note that < is different from <=. The former matches records one through nine, the latter matches records one through ten. If you need ten records, use the latter.
Note that this will walk through your entire file, so if you want to optimize your performance:
awk -F, '{print $3} NR>10{exit}'
This will print the third column. Then if the record number is greater than 10, it will exit. This does not step through your entire file.
Note also that awk's "CSV" matching is very simple; awk does not understand quoted fields, so the record:
red,"orange,yellow",green
has four fields, two of which have double quotes in them. YMMV depending on your input.

Redirect output of one command to different files in shell script

I have a tab seperated string.
I want to copy 1 column to one file and the remaining columns to other file in one go..as that string can modify in between if I use 2 different commands.
I tried:
tab_seperated_string | awk -F"\t" '{ print $2"\t"$3"\t"$4"\t"$5} {print $1}'
2,3,4,5 should go to one file and 1 should go to another file.
You can do like this:
tab_seperated_string | awk -F"\t" '{print $2,$3,$4,$5 > "file2"; print $1 > "file1"}' OFS="\t"
It will then save data to two different files.
By setting OFS to \t, you do not need all the \t in the print statement.
Here is another way if you have many fields that go to one file and first field to another:
awk -F"\t" '{print $1 > "file1"; sub(/[^\t]+\t/,""); print $0 > "file2"}' OFS="\t"
The sub(/[^\t]+\t/,"") removes first field and first tab.

How can i compare the numeric values of the last two fields in a file?

I have a file that contains the following information
organic_apple;2;organic_apple_212_212
organic_tomato;3;organic_tomato_24_29
fruit_juice;5;fruit_juice_15_15
So i want a file that contains the output
organic_apple;2;organic_apple_212
organic_tomato;3;organic_tomato_24_29
fruit_juice;5;fruit_juice_15
compare the last two fields, if they are the same display it once , if not , display them both
I'm writing in unix bash using solaris
Regardless of the number of underscores, compare the last two:
awk 'BEGIN{FS=OFS="_"}$NF==$(NF-1){--NF;$1=$1}1' test.in
Try this :
awk -vOFS=_ -F_ '{if ($2 == $3) print $1, $2; else print $1, $2, $3}' file.txt
This script removes the last field, if it is equal to the one before last:
awk -F "_" '$NF==$(NF-1){$NF=""}1' file

Resources