![如何构造一个 grep & 命令来根据运行时提供的数量来匹配多个模式?](https://linux22.com/image/40095/%E5%A6%82%E4%BD%95%E6%9E%84%E9%80%A0%E4%B8%80%E4%B8%AA%20grep%20%26%20%E5%91%BD%E4%BB%A4%E6%9D%A5%E6%A0%B9%E6%8D%AE%E8%BF%90%E8%A1%8C%E6%97%B6%E6%8F%90%E4%BE%9B%E7%9A%84%E6%95%B0%E9%87%8F%E6%9D%A5%E5%8C%B9%E9%85%8D%E5%A4%9A%E4%B8%AA%E6%A8%A1%E5%BC%8F%EF%BC%9F.png)
我已经出口了一些微软Word将文档转换为纯文本,并使用此函数解析.txt
当前目录中文件的内容:
mo1 () {
for i in *.txt; do
echo "File: $i"
grep -n -HC 1 "$@" "$i"
done
}
如果我有不止一种模式要寻找,我可以做mo1 | grep pattern2
。但是,如果我想做一些事情,其结果将取决于grep -E 'pattern1.*pattern2[.*...]...'
运行时向函数提供的模式数量(即mo1 pattern1 pattern2 [...]
等),该怎么办?我可以看到@
数组可以提供项目的数量,并且我可以通过循环构造一个变量 (finalpattern='$1.*$2.*$3'),该变量最终将成为用于 的表达式grep
。但我想不出如何抽象出在函数中制作表达式的部分?或者有更好/更简单的方法来做这样的事情吗?
答案1
您可以利用printf
内置的。
mo1 () {
for file in *.txt; do
grep -n -C1 "$(printf "%s.*" "$@")" "$file"
done
}
这个简单的版本插入到.*
最后一个元素之后。对于这个特定的用例来说,这并不重要,但在其他情况下(例如),您可能需要在最后grep -o
删除额外的内容。.*
mo1 () {
pattern=$(printf "%s.*" "$@")
pattern=${pattern%??}
for file in *.txt; do
grep -n -C1 "$pattern" "$file"
done
}
在 bash 中,您可以将printf
输出直接放入变量中,这比使用命令替换稍快一些(但这不太可能重要,即使在子 shell 速度很慢的 Cygwin 上也是如此)。
mo1 () {
printf -v pattern "%s.*" "$@"
pattern=${pattern%??}
for file in *.txt; do
grep -n -C1 "$pattern" "$file"
done
}
如果您想在位置参数之间插入单个字符,您可以设置IFS
为该字符并使用"$@"
。但如果分隔符超过一个字符,则这种方法不起作用。在ksh和bash中,如果有一个字符没有出现在模式中,您可以使用它来加入,然后执行替换。例如,在这里,模式包含换行符是没有意义的,因此:
mo1 () {
typeset IFS=$'\n'
typeset pattern="$*"
pattern=${pattern//$'\n'/.*}
for file in *.txt; do
grep -n -C1 "$pattern" "$file"
done
}
在zsh中,当然有一种直接的方法。
mo1 () {
for file in *.txt; do
grep -n -C1 ${(j:.*:)@} $file
done
}
答案2
或者,您可以使用--file
grep 选项:
-f FILE, --file=FILE
Obtain patterns from FILE, one per line. The empty file contains
zero patterns, and therefore matches nothing. (-f is specified by POSIX.)