假设我有文件:
$ 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 解决方案类似?
这应该适用于 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。| 归档时间: |
|
| 查看次数: |
197 次 |
| 最近记录: |