如何将第三列打印到最后一列?


Answers:


108

...或更简单的解决方案:cut -f 3- INPUTFILE 只需添加正确的定界符(-d),您将获得相同的效果。


9
请注意,这仅在所有列之间的定界符完全相同的情况下才有效...例如,您不能将cut与\ d +这样的定界符一起使用。(据我所知。)
Zach Wily 2010年

72
当问题标题为awk时,不接受awk以外的其他答案。如果人们需要awk脚本怎么办?这个答案应该只是一个评论。
syaz

24
@SyaZ:通常我会同意,但是由于板上有很多“免费awk”,我认为有必要展示一种替代方法来完成任务。如果有人向您展示了一种更简单快捷的方法来完成相同任务,您是否会心存感激?海报发布者可能认为awk是唯一的方法,因为对其他问题的回答“不正确,但肯定可以改进”?
Marcin

12
这就是评论的目的。接受最佳的awk答案,并在评论中提供更好的非awk建议。如果人们开始发布不能完全回答问题的答案,那么搜索时就会很烦人(对我而言)。
syaz

12
不仅所有列之间的分隔符必须相同,而且各列之间必须有一个完全相同的分隔符。因此,如果要处理将其输出与定界符对齐的程序,则最好使用awk。
sknaumov

111
awk '{for(i=3;i<=NF;++i)print $i}' 

3
awk'{for(i = 3; i <= NF; ++ i)print $ i}'会更紧凑。:)
user172818

1
谢谢,lh3。我只是在复制和粘贴gawk手册。:)
乔纳森·芬伯格

22
这将失败并显示多行,在打印时每列都会被当作新行处理
meso_2600

12
为了解决分裂问题的输出,我提出这个解决方案:awk '{for(i=3;i<=NF;++i)printf $i""FS ; print ""}'printf将不打印换行符字符,而print ""将其他字段后面添加新行已打印)
lauhub

1
或:echo $(seq 1 10) | awk '{for (i=3; i<=NF; i++) printf $i FS}',其给出:3 4 5 6 7 8 9 10
x-yuri

106
awk '{ print substr($0, index($0,$3)) }'

此处找到解决方案:http :
//www.linuxquestions.org/questions/linux-newbie-8/awk-print-field-to-end-and-character-count-179078/


23
我有点迟了,但这不适用于第一个或第二个字段等于第三个字段(例如3 2 3 4 5)的记录
aleph_null11年

也可以打印内部范围:```#从$ 3(包括)到$ 6(不包括);回声“ 1,2,3,4,5,6,7,8,9” | awk'BEGIN {FS =“,”; OFS =“,”} {print substr($ 0,index($ 0,$ 3),length($ 0)-index($ 0,$ 6)-1)}';; #给出3,4,5''`
splaisan

34

乔纳森·费恩伯格Jonathan Feinberg)的答案将每个字段打印在单独的行上。您可以printf用来重建记录以在同一行上输出,但是您也可以仅将字段向左移动。

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

1
请注意,这仅适用于Gnu awk,NFPOSIX不允许递减。
kvantour

1
@kvantour:它适用于gawk,mawk,MacOS awk(nawk?)。POSIX似乎对是否NF可以递减保持沉默。
暂停,直到另行通知。

这是awk的这些有趣的黑暗角落之一
kvantour

19
awk '{$1=$2=$3=""}1' file

注意:此方法将在1,2,3字段中留下“空白”,但如果您只想查看输出,则不会有问题。


使用`|跟踪该命令 sed s / ^ \ * // | column -t`去除前导空格并对齐其余列
MSpreij 2014年

最后1是什么意思?我应该用哪个关键词搜索awk
Itachi


1
@Nathan,您解决的问题是{$1=$2=$3="";$0=$0;$1=$1}1
kvantour

11

例如,如果要在第三行之后打印同一行中的列,则可以使用:

awk '{for(i=3; i<=NF; ++i) printf "%s ", $i; print ""}'

例如:

Mar 09:39 20180301_123131.jpg
Mar 13:28 20180301_124304.jpg
Mar 13:35 20180301_124358.jpg
Feb 09:45 Cisco_WebEx_Add-On.dmg
Feb 12:49 Docker.dmg
Feb 09:04 Grammarly.dmg
Feb 09:20 Payslip 10459 %2828-02-2018%29.pdf

它将打印:

20180301_123131.jpg
20180301_124304.jpg
20180301_124358.jpg
Cisco_WebEx_Add-On.dmg
Docker.dmg
Grammarly.dmg
Payslip 10459 %2828-02-2018%29.pdf

如我们所见,即使有空格,工资单也会显示在正确的行中。


快速而时尚。谢谢;)
9nz9

这非常好,除非我有一个排除$ NF的问题。设置条件(<= NF)时,我得到了最后一个字段,但第一个字段的第一个字符被砍掉了。我是否在功能方面误解了?
肯·英格拉姆

看来我的问题是^ M卡在最后一列的末尾。没有看到如何删除它。
肯·英格拉姆

8

接下来的行呢:

awk'{$ 1 = $ 2 = $ 3 =“”; 打印}”文件

基于@ ghostdog74的建议。当您过滤线时,我的表现应该更好,例如:

awk'/ ^ exim4-config / {$ 1 =“”; 打印}'文件

简短。也可以sed 's/\s\+//g'在命令末尾进行管道处理并添加以修剪前导空格
jump_monkey

8
awk -v m="\x0a" -v N="3" '{$N=m$N ;print substr($0, index($0,m)+1)}'

这将对给定字段nr。,N之前的内容进行斩波,并打印该行的其余所有内容,包括字段nr.N并保持原始间隔(不重新格式化)。如果字段的字符串也出现在行中的其他位置,则不会发生问题,这是daisaa的答案的问题。

定义一个函数:

fromField () { 
awk -v m="\x0a" -v N="$1" '{$N=m$N; print substr($0,index($0,m)+1)}'
}

并像这样使用它:

$ echo "  bat   bi       iru   lau bost   " | fromField 3
iru   lau bost   
$ echo "  bat   bi       iru   lau bost   " | fromField 2
bi       iru   lau bost 

输出维护所有内容,包括尾随空格

对于以“ / n”为记录分隔符的文件,效果很好,因此行中没有换行符。如果要与其他记录分隔符一起使用,请使用:

awk -v m="\x01" -v N="3" '{$N=m$N ;print substr($0, index($0,m)+1)}'

例如。只要几乎不使用十六进制char nr,几乎所有文件都可以很好地工作。1行内。


4

以下awk命令将打印每行的最后N个字段,并在该行的末尾打印一个新的行字符:

awk '{for( i=6; i<=NF; i++ ){printf( "%s ", $i )}; printf( "\n"); }'

在下面找到一个示例,该示例列出/ usr / bin目录的内容,然后保留最后3行,然后使用awk打印每行的最后4列:

$ ls -ltr /usr/bin/ | tail -3
-rwxr-xr-x 1 root root       14736 Jan 14  2014 bcomps
-rwxr-xr-x 1 root root       10480 Jan 14  2014 acyclic
-rwxr-xr-x 1 root root    35868448 May 22  2014 skype

$ ls -ltr /usr/bin/ | tail -3 | awk '{for( i=6; i<=NF; i++ ){printf( "%s ", $i )}; printf( "\n"); }'
Jan 14 2014 bcomps 
Jan 14 2014 acyclic 
May 22 2014 skype

4
awk '{a=match($0, $3); print substr($0,a)}'

首先,您找到第三列开头的位置。使用substr,您将打印从位置(在本例中为a)到行尾的整行($ 0)。


3

好了,您可以使用正则表达式轻松实现相同的效果。假设分隔符是一个空格,它将看起来像:

awk '{ sub(/[^ ]+ +[^ ]+ +/, ""); print }'

1
我会避免使用正则表达式。意外弄乱的速度可能更慢也更容易。
卡斯卡贝尔

1
它像这样缩短它:awk '{ sub(/([^ ]+ +){2}/, ""); print }'将模式删除两次。
erik 2014年


2

Perl解决方案:

perl -lane 'splice @F,0,2; print join " ",@F' file

这些命令行选项用于:

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

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

  • -a自动拆分模式–将输入行拆分为@F数组。默认为在空白处分割

  • -e 执行Perl代码

splice @F,0,2 干净地从@F数组中删除列0和1

join " ",@F 使用每个元素之间的空格连接@F数组的元素

如果您的输入文件是用逗号分隔而不是用空格分隔,请使用 -F, -lane


Python解决方案:

python -c "import sys;[sys.stdout.write(' '.join(line.split()[2:]) + '\n') for line in sys.stdin]" < file


1

这里有点晚,但是以上似乎都不起作用。尝试使用printf在每个之间插入空格。我选择最后没有换行符。

awk '{for(i=3;i<=NF;++i) printf("%s ",  $i) }'

1
awk '{for (i=4; i<=NF; i++)printf("%c", $i); printf("\n");}'

以与原始文件中相同的顺序打印从第四个字段开始到最后一个字段的记录


抱歉,这不是很正确的答案。它太具体了,但我不知道如何删除
Massimo 2014年

1

在Bash中,您可以将以下语法与位置参数一起使用:

while read -a cols; do echo ${cols[@]:2}; done < file.txt

了解更多信息:在Bash Hackers Wiki上处理位置参数


0

如果仅是忽略前两个字段并且在屏蔽这些字段时不希望有空格(就像上面的一些答案一样):

awk '{gsub($1" "$2" ",""); print;}' file

0
awk '{$1=$2=""}1' FILENAME | sed 's/\s\+//g'

清除前两列,sed删除前导空格。


-2

在AWK中,列称为字段,因此NF是关键

所有行:

awk -F '<column separator>' '{print $(NF-2)}' <filename>

仅第一行:

awk -F '<column separator>' 'NR<=1{print $(NF-2)}' <filename>
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.