如何在第3列本身打印第3个字段

时间:2015-06-03 07:46:35

标签: linux awk

在我的文件中我有3个字段,我只想打印第三列中的第三个字段,但输出到达第一行。请检查我的文件和输出:

cat filename

1st field     2nd field    3rd field
---------     ---------    -----------
a,b,c,d       d,e,f,g,h    1,2,3,4,5,5

q,w,e,r       t,y,g,t,i    9,8,7,6,5,5

我正在使用以下命令仅在第三列中打印第三个字段

cat filename |awk '{print $3}' |tr ',' '\n' 

OUTPUT在第1个字段中打印第3个字段字符串,我希望仅在第3个字段区域打印

first field :-
---------------
1
2
3
4
5 
5

预期输出

1st field     2nd field    3rd field
---------     ---------    -----------
a,b,c,d       d,e,f,g,h     1
                            2
                            3
                            4
                            5 
                            5

q,w,e,r       t,y,g,t,i     9
                            8
                            7
                            6 
                            5
                            5

3 个答案:

答案 0 :(得分:5)

<强>输入

 [akshay@localhost tmp]$ cat file
 1st field     2nd field    3rd field
 ---------     ---------    -----------
 a,b,c,d       d,e,f,g,h    1,2,3,4,5,5

 q,w,e,r       t,y,g,t,i    9,8,7,6,5,5

<强>脚本

 [akshay@localhost tmp]$ cat test.awk
    NR<3 || !NF{ print; next}
    { 
        split($0,D,/[^[:space:]]*/)
        c1=sprintf("%*s",length($1),"")
        c2=sprintf("%*s",length($2),"")
        split($3,A,/,/)
        for(i=1; i in A; i++)
        {   
            if(i==2)
            {
                $1 = c1
                $2 = c2
            }
            printf("%s%s%s%s%d\n",$1,D[2],$2,D[3],A[i]) 
        }
     }

<强>输出

 [akshay@localhost tmp]$ awk -f test.awk file
 1st field     2nd field    3rd field
 ---------     ---------    -----------
 a,b,c,d       d,e,f,g,h    1
                            2
                            3
                            4
                            5
                            5

 q,w,e,r       t,y,g,t,i    9
                            8
                            7
                            6
                            5
                            5

<强>解释

  • NR<3 || !NF{ print; next}
  

NR 为您提供正在处理的记录总数或行号,简而言之 NR 变量包含行号。

     

NF 为您提供记录中的字段总数。

     

next 语句强制awk立即停止处理   当前记录并继续下一个记录。

如果行号小于3或不是NF(表示记录中没有空行的字段),请打印当前记录并转到下一条记录。

  • split($0,D,/[^[:space:]]*/)

由于我们有兴趣保留格式,所以我们在这里的数组D上的字段之间保存分隔符,如果你有 GNU awk ,你可以使用第4个arg for {{ 1}} - 它允许你将线分成2个数组,一个字段和另一个字段之间的分隔符然后你可以只对字段数组进行操作并使用每个字段数组元素之间的分隔符数组进行打印以重建原始split()

  • $0c1=sprintf("%*s",length($1),"")

此处c2=sprintf("%*s",length($2),"")函数用于填充字段(sprintf)长度的空格字符。

  • $1 or $2
  

split(string,array [,fieldsep [,seps]])

     

将字符串分成由fieldsep分隔的片段并存储片段   in array和seps数组中的分隔符字符串。第一件   存储在数组[1]中,第二部分存储在数组[2]中,依此类推。该   第三个参数的字符串值fieldsep是描述的正则表达式   在哪里分割字符串(就像FS可以是一个描述在哪里的正则表达式   拆分输入记录)。如果省略fieldsep,则使用FS的值。   split()返回创建的元素数。

循环直到split($3,A,/,/)为真,我才知道i in Ai=1控制数组遍历的顺序,感谢 Ed Morton < /强>

  • i++

if(i==2) { $1 = c1 $2 = c2 }我们打印i = 1a,b,c,d时,在下一次迭代中,我们会修改d,e,f,g,h$1$2和{{1}我们之前创建的,因为您有兴趣只按要求显示一次。

  • c1

最后打印field1(c2),我们在上面保存的field1和field2之间的分隔符,即printf("%s%s%s%s%d\n",$1,D[2],$2,D[3],A[i]),field2($1),field2和field3之间的分隔符以及数组{{ 1}}元素只是我们从(D[2])创建的元素。

答案 1 :(得分:1)

$ cat tst.awk
NR<3 || !NF { print; next }
{
    front = gensub(/((\S+\s+){2}).*/,"\\1","")
    split($3,a,/,/)
    for (i=1;i in a;i++) {
        print front a[i]
        gsub(/\S/," ",front)
    }
}

$ awk -f tst.awk file
1st field     2nd field    3rd field
---------     ---------    -----------
a,b,c,d       d,e,f,g,h    1
                           2
                           3
                           4
                           5
                           5

q,w,e,r       t,y,g,t,i    9
                           8
                           7
                           6
                           5
                           5

以上使用GNU awk for gensub(),其他awks使用match()+ substr()。它还使用\S\s简写[^[:space:]][[:space:]]

答案 2 :(得分:0)

考虑到列是制表符分隔的,我会说:

awk 'BEGIN{FS=OFS="\t"}
     NR<=2 || !NF {print; next}
     NR>2{n=split($3,a,",")
          for (i=1;i<=n; i++)
              print (i==1?$1 OFS $2:"" OFS ""), a[i]
         }' file
  • 通常会打印第1行,第2行和空行
  • 然后,使用逗号分隔第3个字段作为分隔符。
  • 最后,循环每次打印每件的数量;它首次打印前两列,然后只打印最后一列。

测试

$ awk 'BEGIN{FS=OFS="\t"} NR<=2 || !NF {print; next} NR>2{n=split($3,a,","); for (i=1;i<=n; i++) print (i==1?$1 OFS $2:"" OFS ""), a[i]}' a
1st field   2nd field   3rd field
---------   ---------   -----------
a,b,c,d d,e,f,g,h   1
        2
        3
        4
        5
        5

q,w,e,r t,y,g,t,i   9
        8
        7
        6
        5
        5

注意输出有点难看,因为分隔列的标签会像这样引导它们。