我正在阅读的目录中有一个书籍列表,我想列出书籍中以特定字母的小写和大写结尾的所有单词。
可能有一种使用 cut 或 tr 来做到这一点的方法,但我就是想不出来。有没有办法在管道内使用 glob 来实现它?
我不被允许使用 grep、sed、awk 或 perl。
编辑:我得到的最接近的是:
cat * | tr '[:punct:]' ' '| tr ' ' '\n' | tr -s '\n'| tr '[:upper:]' '[:lower:]' | rev | sort
这样我就可以获得所有单词的列表,每行一个。我们实际上并不需要删除重复项。现在我只需要过滤以 q 开头的单词。
答案1
你可以这样做:
< book.txt \
tr -sc '[:alnum:]_-' '[\n*]' |
tr -d - |
rev |
cut -c1 |
tr -cd eE |
fold -w1 |
sort |
uniq -c
计算单词末尾的e
s 和s(此处定义为字母数字或下划线或连字符的序列),但请注意一些限制:E
- 许多实现(包括 GNU 实现)仅适用于单字节字符。
rev
,尽管 common 不是标准命令。USA
将是一个词和U.S.A.
三个词。- 即使实现能够正确处理字符,如果是以分解形式编写的(后跟 U+0301 组合锐音符),它也会计算 2
e
秒。Stéphane
é
e
- 它不处理连字符。
e
它会在 1.02e+23 或 0xffe.5fp-4 中算一...
如果您仅限于 POSIX shell 和实用程序,您还可以使用ed
:
ed -s book.txt << 'EOF' | sort | uniq -c
g/[^[:alnum:]_-]\{1,\}/s//\
/g
g/-/s///g
g/.*\(.\)$/s//\1/
v/[eE]$/d
,p
Q
EOF
或者与sh
:
l=0 u=0
< book.txt \
tr -sc '[:alnum:]_-' '[\n*]' | {
while IFS= read -r word; do
word=${word%"${word##*[!-]}"}
case $word in
(*e) l=$((l + 1));;
(*E) u=$((u + 1));;
esac
done
printf '%s\t%s\n' "$l" e "$u" E
}