awk FS 与 FPAT 拼图并计算单词但不计算空白字段

daw*_*awg 7 bash awk

假设我有文件:

$ cat file
This, that;
this-that or this.
Run Code Online (Sandbox Code Playgroud)

(行尾的标点符号并不总是存在......)

现在我想计算单词数(单词被定义为一个或多个 ASCII 不区分大小写的字母。)在典型的 POSIX *nix 中你可以这样做:

sed -nE 's/[^[:alpha:]]+/ /g; s/ $//p' file | tr ' ' "\n"  | tr '[:upper:]' '[:lower:]' | sort | uniq -c
   1 or
   2 that
   3 this
Run Code Online (Sandbox Code Playgroud)

使用 grep,您可以缩短一点以仅匹配您定义的单词:

grep -oE '[[:alpha:]]+' file | tr '[:upper:]' '[:lower:]' | sort | uniq -c
# same output
Run Code Online (Sandbox Code Playgroud)

使用 GNU awk,您可以用来FPAT复制仅匹配您想要的内容(忽略排序...):

gawk -v FPAT="[[:alpha:]]+" '
{for (i=1;i<=NF;i++) {seen[tolower($i)]++}}
END {for (e in seen) printf "%4s %s\n", seen[e], e}' file
   3 this
   1 or
   2 that
Run Code Online (Sandbox Code Playgroud)

现在尝试在 POSIX 中复制awk我尝试过:

awk 'BEGIN{FS="[^[:alpha:]]+"}
{ for (i=1;i<=NF;i++) seen[tolower($i)]++ }
END {for (e in seen) printf "%4s %s\n", seen[e], e}' file
   2 
   3 this
   1 or
   2 that
Run Code Online (Sandbox Code Playgroud)

注意2顶部有空白。;这是因为第 1 行末尾和.第 2 行末尾有空白字段。如果删除行末尾的标点符号,此问题就会消失。

您可以通过在 awk 中设置来部分修复它(除了最后一行之外的所有行)RS="",但最后(唯一)行仍然会出现一个空白字段。

我也可以这样修复:

awk 'BEGIN{FS="[^[:alpha:]]+"}
{ for (i=1;i<=NF;i++) if ($i) seen[tolower($i)]++ }
END {for (e in seen) printf "%4s %s\n", seen[e], e}' file
Run Code Online (Sandbox Code Playgroud)

这似乎有点不那么直接。

我是否缺少一个惯用的修复方法来使 POSIX awk 的行为与 GNU awk 的 FPAT 解决方案类似?

anu*_*ava 4

这应该适用于 POSIX/BSD 或任何版本awk

awk -F '[^[:alpha:]]+' '
{for (i=1; i<=NF; ++i) ($i != "") && ++count[tolower($i)]}
END {for (e in count) printf "%4s %s\n", count[e], e}' file

   1 or
   3 this
   2 that
Run Code Online (Sandbox Code Playgroud)
  • 通过使用-F '[^[:alpha:]]+'我们可以在任何非字母字符上分割字段。
  • ($i != "")条件将确保仅计算 中的非空字段seen