如何使用awk打印最大长度的数据?

时间:2017-12-23 01:03:31

标签: bash awk gawk

我有这个输入:

1 happy,t,c,d
2 t,c
3 e,fgh,k
4 yk,j,f
5 leti,j,f,g

我想打印最大项目的长度(使用逗号作为分隔符),这应该产生:

 1 5,1,1,1
 2 1,1
 3 1,3,1
 4 2,1,1
 5 4,1,1,1

然后我想选择第二列的最大值,最后创建:

 1 5
 2 1
 3 3
 4 2
 5 4

我如何在awk中执行此操作?

1)对于我尝试的第一项任务:

awk -v col=$2 -F',' '{OFS=","; for(i=1; i<=NF; i++) print length($i);}' test.data.txt

哪个输出不正确:

7
1
1
1
3
1
3
3
1
4
1
1
6
1
1
1

唯一的问题是我无法正确使用-v选项来只读该列。因此,我将所有数据放在一列中,并从column1和column1和column2之间的空格中添加(从长度开始)值。

2)要选择最大值,我正在做:

awk -F',' '{OFS="\t"; m=length($1); for(i=1; i<=NF; i++) if (length($i) > m) m=length($i); print m}' test.data.txt

这可以正常工作,但是由于第一列的存在,值会被添加到最大值,这样我就可以了:

7
3
3
4
6

而不是:

5
1
3
2
4

最后,我想一次合并这两个进程。有关改进的任何建议吗?

3 个答案:

答案 0 :(得分:4)

awk -F'[, ]' -v OFS="," '{m=length($2);for (i=3;i<=NF;i++) if (length($i) > m) m=length($i)}{print $1,m}' file
1,5
2,1
3,3
4,2
5,4

对于第一种情况:

awk -F'[, ]' -v OFS="," '{printf "%s",$1;for (i=2;i<=NF;i++) printf "%s%s",(i==2?" ":OFS),length($i)}{print ""}'
1 5,1,1,1
2 1,1
3 1,3,1
4 2,1,1
5 4,1,1,1

更短的选择:

awk -F'[, ]' -v OFS="," '{printf "%s ",$1;for (i=2;i<=NF;i++) printf "%s%s",length($i),(i==NF?ORS:OFS)}'

虽然awk中的print打印数据并通过在末尾打印新行来更改行,但printf不会自行更改行。

PS:感谢Ed Morton的宝贵意见。

答案 1 :(得分:3)

我们从这个数据文件开始:

$ cat data
1 happy,t,c,d
2 t,c
3 e,fgh,k
4 yk,j,f
5 leti,j,f,g

第一项任务:

$ awk '{n=split($2,a,/,/); printf "%2s %s",$1,length(a[1]); for(i=2; i<=n; i++) printf ",%s",length(a[i]); print""}' data
 1 5,1,1,1
 2 1,1
 3 1,3,1
 4 2,1,1
 5 4,1,1,1

第二项任务:

$ awk '{n=split($2,a,/,/); max=length(a[1]); for(i=2; i<=n; i++) if (length(a[i])>max)max=length(a[i]); print $1,max}' data
1 5
2 1
3 3
4 2
5 4

如何运作

第二项任务:

  • n=split($2,a,/,/)

    我们将字段2的内容拆分为数组a

  • max=length(a[1])

    我们将数组a的第一个元素的长度分配给awk变量max

  • for(i=2; i<=n; i++) if (length(a[i])>max)max=length(a[i])

    如果数组a的任何后续元素大于max,我们会更新`max。

  • print $1,max

    我们打印第一个字段和max的值。

答案 2 :(得分:2)

尝试打高尔夫球:

gawk -F'[ ,]' '{m=0;for(i=2;i<=NF;i++){l=length($i);if(l>m)m=l}print$1,m}'

perl -MList::Util=max -F'\s+|,' -lne'$,=" ";print shift(@F),max map{length}@F'
perl -MList::Util=max -F'\s+|,' -lne'print"@{[shift(@F),max map{length}@F]}"'
perl -MList::Util=max -F'\s+|,' -lpe'$_="@{[shift(@F),max map{length}@F]}"'    

ruby -F'[ ,]' -lape'$_="#{$F[0]} #{$F[1..-1].map{|e|e.size}.max}"'