使用循环和 awk 查找每列中的最大字符长度

使用循环和 awk 查找每列中的最大字符长度

我正在尝试创建一个脚本来遍历文档并找到列中的最高字符长度并将其返回。该脚本返回 78,78,78,78,而我的目标是 10,11,14,51

for ((i=1;i<=4;i++)); do
  awk -F"|" '{ print length($i) }' contact_d.csv | sort -nr | sed '1!d';
done

contact_d.csv包含这个:(请注意虚拟数据)及其示例

Barrera|Wilkinson|(09) 1466 1886|[email protected]
Hopkins|Sellers|(07) 3814 2364|[email protected]
Hunter|Calderon|(01) 3984 0139|[email protected]

有谁知道为什么 for 循环没有返回我的目标?

答案1

以下代码应该可以工作:

awk -F'|' '{for (i=1;i<=NF;i++) {len=length($i); if (len>lval[i]) {lval[i]=len; lpos[i]=FNR;}}} END{for (i in lval) printf("Longest value of column %d: %d (line %d)\n",i,lval[i],lpos[i])}' contact_d.csv

对于上面的例子,它返回

Longest value of column 1: 7 (line 1)
Longest value of column 2: 9 (line 1)
Longest value of column 3: 14 (line 1)
Longest value of column 4: 26 (line 2)
  • 对于每一行,该脚本将循环遍历所有字段(从 1 到NF字段数),并查看字段的长度(临时存储在变量 中l)是否大于迄今为止找到的最长长度(存储在该字段中)在lval字段(=列)编号索引下的数组变量中。

  • 在第一行,lval尚未初始化,并且它会表现得好像全部lval[i]都是 0(实际上,情况比这更复杂)。

  • i如果当前行字段的长度比 中存储的值长lval[i],则脚本会将字段的当前长度lval[i]和当前行号(可通过“自动”变量访问FNR)存储到数组变量 中lpos

  • 在文件末尾(END条件),它将打印所有列的最长长度和相应位置。我使用循环for (i in lval)遍历所有的构造指数存在于数组中lval,所以我不必将列数保存在额外的变量中(对于类似的东西是必要的for (i=1;i<=ncols;i++)END块中,“字段数”的概念变得有些不明确,尽管实际上awk在访问时通常会使用文件最后一行的相应值)。

请注意,很少需要awk在 shell 循环中调用;它可以完成大部分需要循环完成的事情。

至于您最初尝试失败的原因,您试图将 shell 变量 ( $i) 提供给awk其代码用单引号括起来的脚本(按照建议),但是单引号关闭了 shell 变量的解释(甚至如果没有,它就不会那样工作)。

相关内容