我已经问过类似的问题,但人们误解了我的问题。我问如何生成每个单词的列表,每个文件每个单词的单词计数仅增加一次。
例如,我有一个包含 10 个文件的目录,我想使用 bash 命令生成一个单词列表,该列表的值介于 1-10 之间,具体取决于它们出现在文件中的数量:
10 The
10 and
8 bash
7 command
6 help....
ETC。
我已经知道它将grep -l word *| wc -l
搜索单个单词,但我想创建所有单词的列表。
有没有办法将tr '[A-Z]' '[a-z]' | tr -d '[:punct:]'
其与大写字母的单词不重复并删除标点符号结合起来?
答案1
我会在这里使用 perl :
perl -T -lne '
for (/\w+/g) {$count{lc $_}->{$ARGV}=undef}
END {print "$_: " . keys %{$count{$_}} for keys %count}' ./*
它构造了一个哈希值,哈希值$count{word}
是对哈希值的引用,其键是在其中找到的文件的名称word
(以及我们不关心的值,此处设置为undef
)。
最后,我们只计算每个哈希值(即每个找到的单词)的元素数量(即文件数量)。
答案2
我刚看到原版在这里回答作者:@Mehmet 在搜索不相关的内容时,我发现虽然它有效,但效率非常低,需要再次读取每个文件以获取所有文件中的每个唯一单词! @Jeff 的第二个答案相当复杂,尽管有解释,最糟糕的是它遭受了罪恶cat file |
!
只需要对所有数据进行一次传递即可,并且可以通过有效组合早期答案来制定:
find . -maxdepth 1 -type f -print |
while read file; do
egrep -h -o "[[:alnum:]][[:alnum:]_-]*" "$file" |
tr '[A-Z]' '[a-z]' |
sed "s|^|$file\||"
done |
sort -t '|' -k 2 |
uniq |
awk -F '|' '{
if (lw != $2) {
print fc " " lw;
fc = 0;
}
lw = $2;
fc++;
}'
请注意,如果您的文件名包含路径和/或包含空格,则字段分隔符的选择很重要。我选择这个|
字符是因为它永远不应该是打印的单词的一部分,egrep
并且它不可能出现在文件或目录名称中。
答案3
这应该从所有文件中获取所有单词,对它们进行排序并获取唯一的单词,然后迭代这些单词并计算它出现在多少个文件中。
# find all words from all files within the directory
grep -o -h -E '\w+' directory/*|sort -u | \
while read word;
do
# iterate through each word and find how many files it occurs
c=`grep -l "$word" directory/*|wc -l`
echo "$c $word";
done
答案4
这是单独处理目录中每个文件的方法:
for f in yourdirectory/*; do cat "$f" |
这就是我从文本数据中过滤掉除单词之外的所有内容的方法:
sed 's/\.$//;s/\.\([^0-9]\)/\1/g;s/[][(),;:?!]//g' | tr [A-Z] [a-z] |
但你的方法可能同样有效。 (我想确保不要删除连字符单词中的连字符,也不要删除缩写词中的撇号。)
无论哪种方式,请继续执行以下操作:
tr -s ' ' '\012' | sort -u ; done |
这会生成一个每个文件一个单词列表,所以现在只需:
sort | uniq -c
如果您想要从最频繁到最不频繁的列表,只需添加|sort -nr
。
您可能还需要添加一些额外的标点符号,例如{}
上面末尾的列表sed
,具体取决于您的输入数据。