假设我有两个文件,如下所示:
$ cat search_file.txt
This line contains kwd1.
This line contains kwd2.
This line contains no match.
This line contains no match.
This line contains kwd5.
$ cat search_kwd.sh
grep kwd1 search_file.txt
grep kwd2 search_file.txt
grep kwd3 search_file.txt
grep kwd4 search_file.txt
grep kwd5 search_file.txt
当我运行 search_kwd.sh 时,我得到:
$ sh search_kwd.sh
This line contains kwd1.
This line contains kwd2.
This line contains kwd5.
string
每当 grep 找不到匹配项时我想打印 a 。输出如下:
$ sh search_kwd.sh
This line contains kwd1.
This line contains kwd2.
string
string
This line contains kwd5.
我该如何在 bash 中做到这一点?
答案1
grep
当没有找到任何东西时,以非零代码退出。
从man grep
:
通常,如果选择了一行,则退出状态为 0;如果没有选择行,则退出状态为 1;如果发生错误,则退出状态为 2。
所以你可以使用:
grep kwd3 search_file.txt || echo "string"
答案2
要扩展 @RoVo 的答案,您可以使用 for 循环来迭代所有查询:
for term in "kwd1" "kwd2" "kwd3" "kwd4" "kwd5"; do
grep "$term" search_file.txt || echo "string"`
done
答案3
由于请求的输出似乎每行输入都有一行输出,如果匹配则仅复制该行,如果不匹配则替换该行,因此有比读取文件 5 次并打印更好的方法来做到这一点按照在 search_kwd.sh 文件而不是输入文件中找到的顺序列出行。
相反,您应该一次处理输入文件 1 行。有很多工具可以做到这一点。例如
#!/bin/sh
sed -e '/kwd1/{p;d}
/kwd2/{p;d}
/kwd3/{p;d}
/kwd4/{p;d}
/kwd5/{p;d}
s/.*/string/' search_file.txt
它表示对于每个匹配的关键词打印出该行,然后丢弃它并移动到下一行。如果它遍历了所有关键字并且没有匹配,则将该行更改为字符串(然后隐式打印它)。
你可以使用awk
这样的东西
#!/bin/sh
awk '{ if (/kwd1|kwd2|kwd3|kwd4|kwd5/) { print } else {print "string" }}' search+file.txt
你可以有一个纯 shell 实现
#!/bin/sh
while read -r line
do
case "$line" in
(*"kwd1"*|*"kwd2"*|*"kwd3"*|*"kwd4"*|*"kwd5"*) printf '%s\n' "$line" ;;
(*) printf '%s\n' "string" ;;
esac
done < search_file.txt
您也可以使用 perl、ruby、python。