我需要用一行编写一个脚本,该脚本获取一个文件,并在每行末尾的同一个文件上打印句子中的单词数,只有当单词“word”出现在它上面时。我可以使用另一个脚本来做我想做的事。我的问题是,运行脚本后,文件为空,即我发送给脚本的文件。
这是一行脚本:
#!/bin/bash
cat $1 | ./words_num word | cat $1
Run Code Online (Sandbox Code Playgroud)
#!/bin/bash
while read line; do
temp=`echo $line | grep $1 | wc -l`
if (($temp==1)); then
word_cnt=`echo $line | wc -w`
echo "$line $word_cnt"
else
echo "$line"
fi
done
Run Code Online (Sandbox Code Playgroud)
比如之前的文件是:
bla bla blaa word
words blaa
bla bla
Run Code Online (Sandbox Code Playgroud)
文件后:
bla bla blaa word 4
words blaa 2
bla bla
Run Code Online (Sandbox Code Playgroud)
你能帮我吗?
单线:
cat $1 | ./words_num word | cat $1
Run Code Online (Sandbox Code Playgroud)
是奇特的。它大约相当于:
cat $1 | ./words_num word >/dev/null; cat $1
Run Code Online (Sandbox Code Playgroud)
这不太可能是预期的结果。它也是 UUOC(Useless Use of cat)奖的候选者。
如果打算用修改后的版本覆盖原始文件,那么您可能应该编写:
./words_num word < $1 > tmp.$$; mv tmp.$$ $1
Run Code Online (Sandbox Code Playgroud)
如果您还想在屏幕上看到结果,则:
./words_num word < $1 | tee tmp.$$; mv tmp.$$ $1
Run Code Online (Sandbox Code Playgroud)
如果中断,这两者都会留下一个临时文件。您可以通过以下方式避免这种情况:
#!/bin/bash
trap "rm -f tmp.$$; exit 1" 0 1 2 3 13 15
./words_num word < $1 | tee tmp.$$
mv tmp.$$ $1
trap 0
Run Code Online (Sandbox Code Playgroud)
陷阱设置信号处理程序(EXIT、HUP、INT、QUIT、PIPE、TERM)并删除临时文件(如果存在)并以失败状态退出。在trap 0这样的命令成功退出在端部取消出口俘获。
至于words_num脚本,这似乎要求awk而不是外壳:
#!/bin/bash
[ $# == 0 ] && { echo "Usage: $0 word [file ...]" >&2; exit 1; }
word=$1
shift
awk "/$word/"' { print $0, NF; next } { print }' "$@"
Run Code Online (Sandbox Code Playgroud)
如果您对awk脚本进行编码,则可以减少这种情况,但我更喜欢澄清而不是低于标准的代码。它查找包含单词的行,打印该行以及该行中的字段数,然后移动到下一行。如果该行不匹配,则简单地打印它。赋值和移位意味着"$@"包含所有其他参数到words_num, 并且awk将自动循环通过命名文件,或者如果没有文件被命名,则读取标准输入。
脚本应该检查给定的单词不包含任何斜杠,因为这会弄乱正则表达式(可以用 替换每个出现的单词[/],一个只包含斜杠的字符类)。这种防弹级别留给感兴趣的用户。
cat $1 | ./words_num word | tee $1
Run Code Online (Sandbox Code Playgroud)