用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; }'
您也可以在NF
find列的数量,并在循环中使用它。
$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}'