使用awk打印除第一个字段以外的所有内容
我有一个文件如下所示:使用awk打印除第一个字段以外的所有内容,awk,sed,Awk,Sed,我有一个文件如下所示: 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以外的所有内容”
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;}'
您还可以在
NF
中找到列数,并在循环中使用它。第一次尝试它似乎适用于您的特定情况
awk '{ f = $1; i = $NF; while (i <= 0); gsub(/^[A-Z][A-Z][ ][ ]/,""); print $i, f; }'
awk'{f=$1;i=$NF;while(igawk中的字段分隔符(至少)可以是字符串,也可以是字符(也可以是正则表达式)。如果数据一致,那么这将起作用:
awk -F " " '{print $2,$1}' inputfile
双引号之间有两个空格。awk'{tmp=$1;sub(/^[^]+/,“”);print$0,tmp}'
$1=“”
如本•杰克逊所述留下一个空格,因此使用循环:
awk '{for (i=2; i<=NF; i++) print $i}' filename
awk'{for(i=2;i
将第一个字段设置为”
会在$0
的开头留下一个OFS
的副本。假设OFS
只是一个字符(默认情况下,它是一个空格),我们可以使用substr($0,2)将其删除
。然后,我们将$1
的保存副本附加到cut
命令和-f2-
(POSIX)或--complete
(非POSIX):
让我们将所有记录移动到下一个记录,并将最后一个记录设置为第一个:
$ 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
也许最简洁的方式是:
$ 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 # 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.
$(NF+1)=$1
:最后一个“新”字段的生成器
$1=”“
:将原始第一个字段设置为空
sub(FS,”)
:在前两个操作之后{$(NF+1)=$1;$1=“”}
使用sub除去第一个字段分隔符。最终打印是隐式的
awk '{sub($1 FS,"")}7' YourFile
删除第一个字段和分隔符,然后打印结果(7
是非零值,所以打印$0)。如果您对Perl解决方案持开放态度
perl -lane 'print join " ",@F[1..$#F,0]' file
是一个简单的解决方案,具有一个空格的输入/输出分隔符,可产生:
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
并假设输入/输出分隔符为两个空格:
United Arab Emirates AE
Antigua & Barbuda AG
Netherlands Antilles AN
American Samoa AS
Bosnia and Herzegovina BA
Burkina Faso BF
Brunei Darussalam BN
使用以下命令行选项:
-n
循环输入文件的每一行,不要自动打印每一行
-l
在处理之前删除换行符,然后将其添加回
-a
自动拆分模式–将输入行拆分为@F数组。默认情况下,在空白处拆分
-F
自动拆分修改器,在本例中在“”上拆分(两个空格)
-e
执行以下perl代码
@F
是每行中的单词数组,索引从0开始
$#F
是@F
@F[1..$#F]
是元素1到最后一个元素的数组切片
@F[1..$#F,0]
是元素1到最后一个元素加上元素0的数组切片
选项1
有一种解决方案可用于某些版本的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 '{ # 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.
可以捕获第一个字段,然后使用sub从$0中删除,然后重新打印这两个字段
选择3
即使我们更改FS、OFS和/或添加更多分隔符,它也可以工作。
如果输入文件更改为:
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
输出将是(仍保留分隔符):
该命令可以扩展到多个字段,但只能在现代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
更彻底的解释
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
还有另一种方式
…这将字段2至NF与FS重新连接,并每行输入输出一行
awk '{for (i=2;i<=NF;i++){printf $i; if (i < NF) {printf FS};}printf RS}'
awk'{for(i=2;i如果您对另一个Perl解决方案持开放态度:
perl -ple 's/^(\S+)\s+(.*)/$2 $1/' file
使用cat命令的另一种简单方法
cat filename | awk '{print $2,$3,$4,$5,$6,$1}' > newfilename
对于目前的情况,这是最好的答案,但从技术上讲,这并不能解决如何打印除第一个字段以外的所有内容的问题。@DanMoulding:只要文件在使用两个空格分隔国家/地区代码时保持一致,并且没有其他两个空格同时出现,我的答案就解决了这个问题关于这个问题,请点击此处,因为他们想知道如何打印除第一个字段以外的所有内容(请参见问题标题).这就是我在这里登陆的原因。您的答案显示了如何打印第一个字段,然后再打印第二个字段。虽然这可能是解决OP特殊情况的最佳解决方案,但它并不能解决如何打印除第一个字段以外的所有内容的一般问题。您好@cfisher,这可以在没有循环和额外空间的情况下完成。公式我的两分钱:“如何将awk中的第一个字段移动到最后一个位置”虽然没有回答特定于awk的问题,但我发现这是最有用的,因为awk删除了重复的空格,而cut没有。echo a b c | cut-d'-f 2-
是另一个不错的解决方案-@Luis解决方案在Mac上工作,它不支持对完全懒惰的人的补充;这里是。太好了。用sed:去掉了前导空格>awk{'first=$1;$1=“”;print$0'}| sed's/^//g'
使用VIM pres可以轻松删除空间
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
awk '{for (i=2;i<=NF;i++){printf $i; if (i < NF) {printf FS};}printf RS}'
git diff| \
grep '\-\-git'| \
awk '{print$NF}'| \
awk -F"/" '{for (i=2;i<=NF;i++){printf $i; if (i < NF) {printf FS};}printf RS}'
perl -ple 's/^(\S+)\s+(.*)/$2 $1/' file
cat filename | awk '{print $2,$3,$4,$5,$6,$1}' > newfilename