我正在尝试数辅音和元音的出现在多个文件在 Linux 上,但我希望单独计算每个文件的出现次数。我用
awk -v FS=""'{for ( i=1;i<=NF;i++){if($i ~/[bcdfghjklmnpqrtsvwxyzBCDEFGHJKLMNPQRTSVWXYZ]/)cout_c++ ;else if ($i ~/[aeiouAEIOU]/) count_v++}}END {print FILENAME,count_v,count_c}'
file1 看起来像这样:
bac Dfeg
k87 eH
tRe
rt up
file2 如下所示:
hi
rt2w
PrOt
但它会打印两个文件的出现次数:
file2 7 19
我怎样才能改变它,以便输出如下:
file1 5 12
file2 2 7
答案1
为了回答这个问题后续问题, 这是我的后续答复使用 GNU awk (现在修改为仅将 b、c、d 等计算为非元音,而不是每个不是 aeiou 的字符,例如,À
如é
所提到的@StéphaneChazelas在评论中):
$ awk -v IGNORECASE=1 '
{
v_cnt += gsub(/[aeiou]/,"")
c_cnt += gsub(/[bcdfghjklmnpqrtsvwxyz]/,"")
}
ENDFILE {
print FILENAME, v_cnt+0, c_cnt+0
v_cnt = c_cnt = 0
}
' file1 file2
file1 5 12
file2 2 7
我将把它作为一个简单的练习,说明如何修改我之前的答案中的 POSIX awk 等效项。
如果您还想要某种指示,如果上面的括号表达式中未列出字母字符,则只需进行以下调整:
awk -v IGNORECASE=1 '
{
v_cnt += gsub(/[aeiou]/,"")
c_cnt += gsub(/[bcdfghjklmnpqrtsvwxyz]/,"")
}
/[[:alpha:]]/ {
gsub(/[^[:alpha:]]+/,"")
printf "Warning %s[%d]: Unexpected chars found: %s\n", FILENAME, FNR, $0 > "/dev/stderr"
}
ENDFILE {
print FILENAME, v_cnt+0, c_cnt+0
v_cnt = c_cnt = 0
}
' file1 file2
如何处理当然可以用各种不同的方式和不同的输出量+细节来处理。
答案2
一种方式使用珀尔如下:
perl -lne '$,=" ";
$A[0] += +lc =~ tr/aeiou//;
$A[1] += s/(?![aeiou])[[:alpha:]]//gi;
print $ARGV, splice @A if eof;
' file1 file2
输出:
file1 5 12
file2 2 7
评论;
- 数组@A 的第一个元素累加元音的运行总数。
- 第二个元素累积辅音的运行总数,这些辅音是字母表减去元音的集合。
- 在当前文件的末尾,数据被转储。注意,拼接的副作用会使数组无效。