awk命令从第3列打印到第n列

时间:2016-09-14 13:56:59

标签: unix awk

如果文件中有'n'列,如何使用unix中的awk命令从第3列打印到最后列。我正在使用cut命令,但我需要awk命令。我正在尝试使用awk -F " " '{ for{i=3;i<=NF;i++) print $i}',我正在获取输出,但格式不正确。任何人都可以建议我正确的命令。

5 个答案:

答案 0 :(得分:2)

将Ed Morton的答案结合在一起:

我们得到这样的东西:

awk '{sub(/^(\S+\s*){2}/,""); sub(/(\s*\S+){2}$/,"")}1'
#     ^^^^^^^^^^^^^^^^^^^^^^  ^^^^^^^^^^^^^^^^^^^^^^
#     remove 2 first cols      remove 2 last cols

您可以根据列来适应您的确切需求。

请参阅此输入的示例:

$ paste -d ' ' <(seq 5) <(seq 2 6) <(seq 3 7) <(seq 4 8) <(seq 5 9) 
1 2 3 4 5
2 3 4 5 6
3 4 5 6 7
4 5 6 7 8
5 6 7 8 9

我们打印第3栏:

$ awk '{sub(/^(\S+\s*){2}/,""); sub(/(\s*\S+){2}$/,"")}1' <(paste -d ' ' <(seq 5) <(seq 2 6) <(seq 3 7) <(seq 4 8) <(seq 5 9))
3
4
5
6
7

答案 1 :(得分:1)

假设你的字段是空格分隔的,那么使用GNU awk for gensub():

$ cat file
a b c d e f
g h i j k l

$ awk '{print gensub(/(\S\s){2}/,"",1)}' file
c d e f
i j k l

一般情况下,从字段3到字段5进行打印,如果它们是空白的,请使用GNU awk再次使用gensub()分隔:

$ awk '{print gensub(/(\S\s){2}((\S\s){2}\S).*/,"\\2",1)}' file
c d e
i j k

或第3个arg匹配():

$ awk 'match($0,/(\S\s){2}((\S\s){2}\S)/,a){print a[2]}' file
c d e
i j k

或者一般来说,如果它们被任何一个字符分开:

$ awk '{print gensub("([^"FS"]"FS"){2}(([^"FS"]"FS"){2}[^"FS"]).*","\\2",1)}' file
c d e
i j k

$ awk 'match($0,"([^"FS"]"FS"){2}(([^"FS"]"FS"){2}[^"FS"])",a){print a[2]}' file
c d e
i j k

如果字段由字符串而不是单字符分隔,但RS是单个字符,那么您应该暂时将FS更改为RS(根据定义,您知道记录中不能存在),这样您就可以在括号表达式中否定它:

$ cat file
aSOMESTRINGbSOMESTRINGcSOMESTRINGdSOMESTRINGeSOMESTRINGf
gSOMESTRINGhSOMESTRINGiSOMESTRINGjSOMESTRINGkSOMESTRINGl

$ awk -F'SOMESTRING' '{gsub(FS,RS)} match($0,"([^"RS"]"RS"){2}(([^"RS"]"RS"){2}[^"RS"])",a){gsub(RS,FS,a[2]); print a[2]}' file
cSOMESTRINGdSOMESTRINGe
iSOMESTRINGjSOMESTRINGk

如果FS和RS都是多字符,则有各种选项但最简单的方法是使用NUL字符或您知道的其他字符不能出现在输入文件中而不是RS作为临时替换FS:

$ awk -F'SOMESTRING' '{gsub(FS,"\0")} match($0,/([^\0]\0){2}(([^\0]\0){2}[^\0])/,a){gsub("\0",FS,a[2]); print a[2]}' file
cSOMESTRINGdSOMESTRINGe
iSOMESTRINGjSOMESTRINGk

如果需要,显然可以在上面的最终gsub()中将FS改为OFS。

如果FS是regexp而不是字符串,并且你想在输出中保留它,那么你需要查看GNU awk以获得第4个arg for split()。

答案 2 :(得分:0)

如果你不介意规范空间,最直接的方法是

$ seq 11 40 | pr -6ts' ' | awk '{$1=$2=""}1' | sed -r 's/^ +//'

21 26 31 36
22 27 32 37
23 28 33 38
24 29 34 39
25 30 35 40

行动

$ seq 11 40 | pr -6ts' '

11 16 21 26 31 36
12 17 22 27 32 37
13 18 23 28 33 38
14 19 24 29 34 39
15 20 25 30 35 40

输入

load

答案 3 :(得分:0)

您的尝试已接近但似乎会在新行上打印每一列。 为了纠正这个问题,我们创建了一个名为&#39; line&#39;并将其初始化为空字符串。我们第一次进入循环时只需将列添加到&#39; line&#39;。从那时起,我们将附加到&#39; line&#39;使用字段分隔符和下一列。最后,我们打印&#39; line&#39;。这将发生在文件中的每一行。

awk '{line="";for(i=3;i<=NF;i++) if(i==3) line=$i; else line=line FS $i; print line}'

在这个例子中,我假设使用awk的默认字段分隔符。任何小于3的行都会打印空白行。

答案 4 :(得分:0)

从第三列打印到结束然后 cat filename | awk&#39; {for(i = 1; i&lt; 3; i ++)$ i =&#34;&#34 ;; print $ 0}&#39;

相关问题