使用管道读取文件,运行脚本并写入同一个文件

use*_*488 5 bash

我需要用一行编写一个脚本,该脚本获取一个文件,并在每行末尾的同一个文件上打印句子中的单词数,只有当单词“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)

你能帮我吗?

Jon*_*ler 5

单线:

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将自动循环通过命名文件,或者如果没有文件被命名,则读取标准输入。

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


enn*_*ler 3

cat $1 | ./words_num word | tee $1
Run Code Online (Sandbox Code Playgroud)

  • 对于小文件来说,这主要靠运气——如果幸运的话,最多可达几千字节。有多大取决于您正在使用的操作系统上管道缓冲区的大小,可以从大约 4 KiB(POSIX 最小值)到 64 KiB 左右,但通常为 5 KiB(历史先例)。它还取决于 shell 在启动 `tee` 之前启动 `cat`,并且调度对您有利。如果您处理的文件大小为兆字节,则此操作将会失败。 (4认同)