Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Printing everything except the first field with awk

Tags:

sed

awk

I have a file that looks like this:

AE  United Arab Emirates
AG  Antigua & Barbuda
AN  Netherlands Antilles
AS  American Samoa
BA  Bosnia and Herzegovina
BF  Burkina Faso
BN  Brunei Darussalam

And I 'd like to invert the order, printing first everything except $1 and then $1:

United Arab Emirates AE

How can I do the "everything except field 1" trick?

like image 614
cfischer Avatar asked Nov 16 '10 19:11

cfischer


People also ask

How do I ignore the first row in awk?

The following `awk` command uses the '-F' option and NR and NF to print the book names after skipping the first book. The '-F' option is used to separate the content of the file base on \t. NR is used to skip the first line, and NF is used to print the first column only.

How do you get to the first field in awk?

awk to print the first column. The first column of any file can be printed by using $1 variable in awk. But if the value of the first column contains multiple words then only the first word of the first column prints. By using a specific delimiter, the first column can be printed properly.

What is awk '{ print $3 }'?

txt. If you notice awk 'print $1' prints first word of each line. If you use $3, it will print 3rd word of each line.

What is awk '{ print $2 }'?

awk '{ print $2; }' prints the second field of each line. This field happens to be the process ID from the ps aux output. xargs kill -${2:-'TERM'} takes the process IDs from the selected sidekiq processes and feeds them as arguments to a kill command.


9 Answers

$1="" leaves a space as Ben Jackson mentioned, so use a for loop:

awk '{for (i=2; i<=NF; i++) print $i}' filename

So if your string was "one two three", the output will be:

two
three

If you want the result in one row, you could do as follows:

awk '{for (i=2; i<NF; i++) printf $i " "; print $NF}' filename

This will give you: "two three"

like image 135
7winkie Avatar answered Sep 28 '22 21:09

7winkie


Assigning $1 works but it will leave a leading space: awk '{first = $1; $1 = ""; print $0, first; }'

You can also find the number of columns in NF and use that in a loop.

like image 35
Ben Jackson Avatar answered Sep 28 '22 22:09

Ben Jackson


Use the cut command with -f 2- (POSIX) or --complement (not POSIX):

$ echo a b c | cut -f 2- -d ' '
b c
$ echo a b c | cut -f 1 -d ' '
a
$ echo a b c | cut -f 1,2 -d ' '
a b
$ echo a b c | cut -f 1 -d ' ' --complement
b c
like image 36
zeleniy Avatar answered Sep 28 '22 21:09

zeleniy


Maybe the most concise way:

$ awk '{$(NF+1)=$1;$1=""}sub(FS,"")' infile
United Arab Emirates AE
Antigua & Barbuda AG
Netherlands Antilles AN
American Samoa AS
Bosnia and Herzegovina BA
Burkina Faso BF
Brunei Darussalam BN

Explanation:

$(NF+1)=$1: Generator of a "new" last field.

$1="": Set the original first field to null

sub(FS,""): After the first two actions {$(NF+1)=$1;$1=""} get rid of the first field separator by using sub. The final print is implicit.

like image 26
Juan Diego Godoy Robles Avatar answered Sep 28 '22 21:09

Juan Diego Godoy Robles


awk '{sub($1 FS,"")}7' YourFile

Remove the first field and separator, and print the result (7 is a non zero value so printing $0).

like image 37
NeronLeVelu Avatar answered Sep 28 '22 23:09

NeronLeVelu


awk '{ saved = $1; $1 = ""; print substr($0, 2), saved }'

Setting the first field to "" leaves a single copy of OFS at the start of $0. Assuming that OFS is only a single character (by default, it's a single space), we can remove it with substr($0, 2). Then we append the saved copy of $1.

like image 43
dubiousjim Avatar answered Sep 28 '22 22:09

dubiousjim


If you're open to a Perl solution...

perl -lane 'print join " ",@F[1..$#F,0]' file

is a simple solution with an input/output separator of one space, which produces:

United Arab Emirates AE
Antigua & Barbuda AG
Netherlands Antilles AN
American Samoa AS
Bosnia and Herzegovina BA
Burkina Faso BF
Brunei Darussalam BN

This next one is slightly more complex

perl -F`  ` -lane 'print join "  ",@F[1..$#F,0]' file

and assumes that the input/output separator is two spaces:

United Arab Emirates  AE
Antigua & Barbuda  AG
Netherlands Antilles  AN
American Samoa  AS
Bosnia and Herzegovina  BA
Burkina Faso  BF
Brunei Darussalam  BN

These command-line options are used:

  • -n loop around every line of the input file, do not automatically print every line

  • -l removes newlines before processing, and adds them back in afterwards

  • -a autosplit mode – split input lines into the @F array. Defaults to splitting on whitespace

  • -F autosplit modifier, in this example splits on ' ' (two spaces)

  • -e execute the following perl code

@F is the array of words in each line, indexed starting with 0
$#F is the number of words in @F
@F[1..$#F] is an array slice of element 1 through the last element
@F[1..$#F,0] is an array slice of element 1 through the last element plus element 0

like image 41
Chris Koknat Avatar answered Sep 28 '22 21:09

Chris Koknat


Let's move all the records to the next one and set the last one as the first:

$ awk '{a=$1; for (i=2; i<=NF; i++) $(i-1)=$i; $NF=a}1' file
United Arab Emirates AE
Antigua & Barbuda AG
Netherlands Antilles AN
American Samoa AS
Bosnia and Herzegovina BA
Burkina Faso BF
Brunei Darussalam BN

Explanation

  • a=$1 save the first value into a temporary variable.
  • for (i=2; i<=NF; i++) $(i-1)=$i save the Nth field value into the (N-1)th field.
  • $NF=a save the first value ($1) into the last field.
  • {}1 true condition to make awk perform the default action: {print $0}.

This way, if you happen to have another field separator, the result is also good:

$ cat c
AE-United-Arab-Emirates
AG-Antigua-&-Barbuda
AN-Netherlands-Antilles
AS-American-Samoa
BA-Bosnia-and-Herzegovina
BF-Burkina-Faso
BN-Brunei-Darussalam

$ awk 'BEGIN{OFS=FS="-"}{a=$1; for (i=2; i<=NF; i++) $(i-1)=$i; $NF=a}1' c
United-Arab-Emirates-AE
Antigua-&-Barbuda-AG
Netherlands-Antilles-AN
American-Samoa-AS
Bosnia-and-Herzegovina-BA
Burkina-Faso-BF
Brunei-Darussalam-BN
like image 23
fedorqui 'SO stop harming' Avatar answered Sep 28 '22 23:09

fedorqui 'SO stop harming'


The field separator in gawk (at least) can be a string as well as a character (it can also be a regex). If your data is consistent, then this will work:

awk -F "  " '{print $2,$1}' inputfile

That's two spaces between the double quotes.

like image 24
Dennis Williamson Avatar answered Sep 28 '22 22:09

Dennis Williamson