2016-09-14 1005 views
0

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

+0

你能得到样品输入/ output ...是否定义了列空间? – zee

+0

'cut'有什么问题? –

回答

0

你试图接近,但看来,它会在新行打印每列。 要纠正这个问题,我们创建一个名为'line'的变量并将其初始化为一个空字符串。我们第一次进入循环时,我们只需将该列添加到“行”中。从这一点开始,我们将添加字段分隔符和下一列。最后,我们打印'行'。这将发生在文件中的每一行。

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

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

+0

非常感谢Wayne。它非常好 – Srinivas

2

在结合埃德莫顿的答案:

我们得到了这样的事:

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 
+0

“{print $ 3}”有什么问题? – karakfa

+0

@karakfa它不是太通用:) – fedorqui

0

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

$ awk '{$1=$2=""}1' | sed -r 's/^ +//' 

在行动

$ 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 
1

假设你的字段是用空格隔开的与GNU AWK然后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 

或第三个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是多声道AR则有不同的选择,但最简单的就是用你知道能不能出现在你的输入文件,而不是RS作为临时更换FS的NULL字符或其它字符:

$ 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 

明显变化FS到OFS中如果需要的话,最后的gsub()会被提供。

如果FS是一个正则表达式,而不是一个字符串,并要保留它的输出,那么你需要看看GNU AWK第四届ARG的分裂()。

+1

精湛! ++++++ – fedorqui

0

为了从第三塔打印到直到端然后 猫文件名| AWK '{对于(I = 1;我< 3; i ++在)$ I = “”;打印$ 0}'