5

我需要编写一个脚本,其中一行获取一个文件,并在每行末尾的同一文件上打印句子中的单词数,只有当单词“word”出现在它上面时。我可以使用另一个可以做任何我想做的脚本。我的问题是,在我运行脚本后,文件为空,即我发送给脚本的文件。

这是单行脚本:

#!/bin/bash
cat $1 | ./words_num word | cat $1

words_num

#!/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

例如,之前的文件是:

bla bla blaa word
words blaa
bla bla

文件后:

bla bla blaa word 4
words blaa 2
bla bla

你能帮我吗?

4

2 回答 2

5

单线:

cat $1 | ./words_num word | cat $1

很奇特。它大约相当于:

cat $1 | ./words_num word >/dev/null; cat $1

这不太可能是预期的结果。它也是 UUOC(无用使用cat)奖的候选者。

如果打算用修改后的版本覆盖原始文件,那么您可能应该写:

./words_num word < $1 > tmp.$$; mv tmp.$$ $1

如果您还想在屏幕上查看结果,那么:

./words_num word < $1 | tee tmp.$$; mv tmp.$$ $1

如果中断,这两者都会留下一个临时文件。您可以通过以下方式避免这种情况:

#!/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

陷阱设置信号处理程序(EXIT、HUP、INT、QUIT、PIPE、TERM)并删除临时文件(如果存在)并以失败状态退出。最后trap 0的 取消退出陷阱,因此命令成功退出。

至于words_num脚本,这似乎需要awk而不是 shell:

#!/bin/bash
[ $# == 0 ] && { echo "Usage: $0 word [file ...]" >&2; exit 1; }
word=$1
shift
awk "/$word/"' { print $0, NF; next } { print }' "$@"

如果您对awk脚本进行代码打高尔夫球,您可以减少这种情况,但我更喜欢澄清低于标准的代码。它查找包含该单词的行,打印该行以及该行中的字段数,然后移至下一行。如果该行不匹配,则简单地打印它。赋值和移位意味着"$@"包含所有其他参数words_num,并且awk将自动循环通过命名文件,或者如果没有命名文件则读取标准输入。

脚本应该检查给定的单词是否不包含任何斜杠,因为这会弄乱正则表达式(可以将出现的每个替换为[/],一个只包含斜杠的字符类)。这种防弹级别留给感兴趣的用户。

于 2013-10-23T17:38:50.460 回答
3
cat $1 | ./words_num word | tee $1
于 2013-04-21T14:33:28.117 回答