用awk打印除第一个字段以外的所有内容

我有一个如下所示的文件:

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

我想反转订单,首先打印除$ 1和$ 1之外的所有东西:

 United Arab Emirates AE 

我怎样才能做到“除场1之外的一切”技巧?

分配$1作品,但会留下一个领先的空间: awk '{first = $1; $1 = ""; print $0, first; }' awk '{first = $1; $1 = ""; print $0, first; }'

您也可以在NFfind列的数量,并在循环中使用它。

$1=""离开了Ben Jackson所说的空间,所以使用for循环:

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

所以如果你的string是“一二三”,输出将是:


如果你想在一行结果,你可以做如下:

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

这会给你:“二三”

使用带有--complement选项的cut命令:

 $ echo abc | cut -f 1 -d ' ' a $ echo abc | cut -f 1,2 -d ' ' ab $ echo abc | cut -f 1 -d ' ' --complement bc 

也许最简洁的方式:

 $ 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 

说明:

$(NF+1)=$1 :“新”最后一个字段的生成器。

$1="" :将原来的第一个字段设置为空

sub(FS,"") :在前两个动作{$(NF+1)=$1;$1=""} ,用sub去掉第一个字段分隔符。 最终的印刷品是隐含的。

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

将第一个字段设置为"" ,在$0的开始处留下OFS的单个副本。 假设OFS只是一个字符(默认情况下,它是一个空格),我们可以用substr($0, 2)删除它。 然后我们追加保存的$1副本。

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

删除第一个字段和分隔符,并打印结果( 7是非零值,所以打印$ 0)。

gawk中的字段分隔符(至less)可以是string以及字符(也可以是正则expression式)。 如果你的数据是一致的,那么这将工作:

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

这是双引号之间的两个空格。

awk '{ tmp = $1; sub(/^[^ ]+ +/, ""); print $0, tmp }'

让我们把所有logging移到下一个logging,并把最后一个logging设置为第一个:

 $ 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 

说明

  • a=$1将第一个值保存到临时variables中。
  • for (i=2; i<=NF; i++) $(i-1)=$i将第N个字段值保存到第(N-1)个字段中。
  • $NF=a将第一个值( $1 )保存到最后一个字段中。
  • {}1使awk执行默认操作的真实条件: {print $0}

这样,如果你碰巧有另一个字段分隔符,结果也是好的:

 $ 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 

第一次刺伤它似乎适用于您的特定情况。

 awk '{ f = $1; i = $NF; while (i <= 0); gsub(/^[AZ][AZ][ ][ ]/,""); print $i, f; }' 

如果你打开一个Perl解决scheme…

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

是一个简单的解决scheme,具有一个空间的input/输出分隔符,它产生:

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

下一个稍微复杂一些

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

并假定input/输出分隔符是两个空格:

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

这些命令行选项被使用:

  • -n循环input文件的每一行,不要自动打印每一行

  • -l在处理之前删除换行符,然后将其添加回来

  • -a自动分割模式 – 将input行分割成@F数组。 默认分割为空格

  • -F autosplit修饰符,在这个例子中拆分为''(两个空格)

  • -e执行下面的perl代码

@F是每行中的单词数组,索引从0开始
$#F@F的字数
@F[1..$#F]是元素1到最后一个元素的数组切片
@F[1..$#F,0]是元素1到最后一个元素加上元素0的数组切片

选项1

有一个解决scheme可以与awk的某些版本一起工作:

 awk '{ $(NF+1)=$1;$1="";$0=$0;} NF=NF ' infile.txt 

说明:

  $(NF+1)=$1 # add a new field equal to field 1. $1="" # erase the contents of field 1. $0=$0;} NF=NF # force a re-calc of fields. # and use NF to promote a print. 

结果:

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

但是,旧版本的awk可能会失败。


选项2

 awk '{ $(NF+1)=$1;$1="";sub(OFS,"");}1' infile.txt 

那是:

 awk '{ # call awk. $(NF+1)=$1; # Add one trailing field. $1=""; # Erase first field. sub(OFS,""); # remove leading OFS. }1' # print the line. 

请注意,需要擦除的是OFS,而不是FS。 当字段$ 1被赋值时,该行被重新计算。 这将FS的所有运行改变为一个OFS。


但是,即使这个选项仍然失败,有几个分隔符,如通过更改OFS清楚地显示:

 awk -v OFS=';' '{ $(NF+1)=$1;$1="";sub(OFS,"");}1' infile.txt 

该行将输出:

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

这表明FS的运行正在变成一个OFS。
避免这种情况的唯一方法是避免现场重新计算。
一个可以避免重新计算的函数是sub。
第一个字段可以被捕获,然后从$ 0中删除,然后重新打印。

选项3

 awk '{ a=$1;sub("[^"FS"]+["FS"]+",""); print $0, a;}' infile.txt a=$1 # capture first field. sub( " # replace: [^"FS"]+ # A run of non-FS ["FS"]+ # followed by a run of FS. " , "" # for nothing. ) # Default to $0 (the whole line. print $0, a # Print in reverse order, with OFS. United Arab Emirates AE Antigua & Barbuda AG Netherlands Antilles AN American Samoa AS Bosnia and Herzegovina BA Burkina Faso BF Brunei Darussalam BN 

即使我们改变FS,OFS和/或添加更多的分隔符,它也可以工作。
如果input文件更改为:

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

该命令更改为:

 awk -vFS='.' -vOFS=';' '{a=$1;sub("[^"FS"]+["FS"]+",""); print $0,a;}' infile.txt 

输出将是(仍然保留分隔符):

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

该命令可以扩展到几个字段,但只能使用现代的awk和–re-interval选项。 原始文件上的这个命令:

 awk -vn=2 '{a=$1;b=$2;sub("([^"FS"]+["FS"]+){"n"}","");print $0,a,b;}' infile.txt 

会输出这个:

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

还有一个sed选项…

  sed 's/\([^ ]*\) \(.*\)/\2 \1/' inputfile.txt 

解释…

 Swap \([^ ]*\) = Match anything until we reach a space, store in $1 \(.*\) = Match everything else, store in $2 With \2 = Retrieve $2 \1 = Retrieve $1 

更彻底的解释…

 s = Swap / = Beginning of source pattern \( = start storing this value [^ ] = text not matching the space character * = 0 or more of the previous pattern \) = stop storing this value \( = start storing this value . = any character * = 0 or more of the previous pattern \) = stop storing this value / = End of source pattern, beginning of replacement \2 = Retrieve the 2nd stored value \1 = Retrieve the 1st stored value / = end of replacement 

另一种方式

…这与FS重新加场2到NF,并且每行input一行

 awk '{for (i=2;i<=NF;i++){printf $i; if (i < NF) {printf FS};}printf RS}' 

我用git来查看在我的工作目录中修改了哪些文件:

 git diff| \ grep '\-\-git'| \ awk '{print$NF}'| \ awk -F"/" '{for (i=2;i<=NF;i++){printf $i; if (i < NF) {printf FS};}printf RS}'