如何在awk中打​​印没有字段分隔符的行?

Luk*_*sCB 3 regex sorting awk list

我有这样的数据(文件被称为list-in.dat)

a ; b ; c ; i
d
e ; f ; a ; b
g ; h ; i
Run Code Online (Sandbox Code Playgroud)

并且我想要一个这样的列表(输出文件list-out.dat),其中包含所有项目,按字母顺序(不区分大小写)和每个唯一项目仅一次。

a
b
c
d
e
f
g
h
i
Run Code Online (Sandbox Code Playgroud)

我的尝试是:

awk -F " ; " ' BEGIN { OFS="\n" ; } {for(i=0; i<=NF; i++) print $i} ' file-in.dat | uniq | sort -uf > file-out.dat
Run Code Online (Sandbox Code Playgroud)

但我最终得到了所有的蚂蚁,除了那些只有一个项目的行:

a
b
c
e
f
g
h
i
Run Code Online (Sandbox Code Playgroud)

无论一行中有多少项目/如果缺少字段分隔符,我如何获得所有(唯一的、已排序的)项目?

anu*_*ava 5

使用gnu-awk:

awk -F '[[:blank:]]*;[[:blank:]]*' '{
   for (i=1; i<=NF; i++) uniq[$i]
}
END {
   PROCINFO["sorted_in"]="@ind_str_asc"
      for (i in uniq)
         print i
}' file
Run Code Online (Sandbox Code Playgroud)
a
b
c
d
e
f
g
h
i
Run Code Online (Sandbox Code Playgroud)

对于non-gnu awk使用:

awk -F '[[:blank:]]*;[[:blank:]]*' '{for (i=1; i<=NF; i++) uniq[$i]} 
END{for (i in uniq) print i}' file | sort 
Run Code Online (Sandbox Code Playgroud)

  • 非常感谢您对 Ed 进行基准测试。我想这也是OP在上面的评论中所说的。 (3认同)
  • 将(非 gnu)答案视为“正确”,因为它是最快的解决方案(至少在我的系统上)。 (2认同)
  • 无论如何,对于某些数据分布来说,看起来首先填充“uniq[]”而不是仅仅打印每个字段更快。我刚刚使用 `awk 'BEGIN{for (i=1; i&lt;=100000; i++) for (j=1; j&lt;=10; j++) printf "%s%s", i+j, ( 创建了一个文件j&lt;10?OFS:ORS)}' &gt; file`,然后运行 ​​`time awk '{for (i=1; i&lt;=NF; i++) unq[$i]} END{for (i in unq) print i }' 文件 | sort &gt; /dev/null` 在运行 `time awk '{for (i=1; i&lt;=NF; i++) print $i}' 文件时获取了 `real 0m0.475s user 0m0.389s sys 0m0.091s` sort -u &gt; /dev/null` 采用了 `real 0m2.321s user 0m2.343s sys 0m0.030s`。你生活和学习... (2认同)
  • 上面的文件有很多重复的值。对于由 `awk 'BEGIN{for (i=1; i&lt;=1000000; i+=10) for (j=1; j&lt;=10; j++) printf "%s%s" 创建的没有重复值的文件, i+j, (j&lt;10?OFS:ORS)}' &gt; file` 两种方法的时间在 `real 0m3.196s user 0m3.139s sys 0m0.170s` 周围几乎相同。因此,首先填充“uniq[]”并在其上循环似乎是提高执行速度的更好方法,因为它永远不会变慢,有时甚至更快。根本不是我所期望的! (2认同)
  • @EdMorton,非常感谢 Ed 先生和 anubhava 先生进行了这次愉快的谈话,我也从这次谈话中学到了东西,谢谢你们,并保持安全,你们两位宝石:) (2认同)
  • @EdMorton:两个 `awk` 版本都比 `sed` 快得多,后者用 `\n` 替换分隔符,通过管道传输到 `sort -u` 顺便说一句 (2认同)