我有一个包含此搜索的shell脚本:
find . -type f -exec grep -iPho "barh(li|mar|ag)" {} ;
我想捕获每个字符串grep命令查找并将其发送我将创建的函数,我将创建名为" Parser"
parser(){
# do stuff with each single grep result found
}
如何完成?这是对的吗?
find . -type f -exec grep -iPho "barh(li|mar|ag)" {parser $1} ;
我不想将整个查找命令结果输出到函数
只有外壳才能执行功能。您需要在find
中使用bash -c
才能执行它。这也是您需要导出功能的原因,以便新过程看到它。
parser() {
while IFS= read -r line; do
echo "Processing line: $line"
done <<< "$1"
}
export -f parser
find . -type f -exec bash -c 'parser "$(grep -iPho "barh(li|mar|ag)" "$1")"' -- {} ;
上面的代码将从file1,然后将file2等发送到您的函数进行处理。它不会一个一个一个线发送每行,因此您需要在功能中的行上循环。如果文件中未出现您的正则表达式,它将 still 用空输入调用您的功能!
这可能不是最适合您的解决方案,因此让我们尝试在bash -c
语句中添加循环,而则真正一个一个接一个地处理行:
parser() {
echo "Processing line: $1"
}
export -f parser
find . -type f -exec bash -c 'grep -iPho "barh(li|mar|ag)" "$@" | while IFS= read -r line; do parser "$line"; done' -- {} +
编辑:非常好的简单解决方案不使用@gniourf_gniourf建议的bash -c
:
parser() {
echo "Processing line: $1"
}
find . -type f -exec grep -iPho "barh(li|mar|ag)" {} + | while IFS= read -r line; do parser "$line"; done
此方法效果很好,将一一处理每行。您也不需要使用此方法导出您的功能。但是您必须关心一些可能会让您感到惊讶的事情。
管道中的每个命令均以其自己的子壳执行,并且parser
功能中的任何变量分配或您的while
一般都会在从该子壳中返回后丢失。如果您正在编写脚本,那么简单的shopt -s lastpipe
就足够了,并在当前的Shell环境中运行最后一个管道命令。或者您可以使用流程替代:
parser() {
echo "Processing line: $1"
}
while IFS= read -r line; do
parser "$line";
done < <(find . -type f -exec grep -iPho "barh(li|mar|ag)" {} +)
请注意,在以前的bash -c
示例中,您将遇到相同的行为,并且您的变量分配也将丢失。
您需要导出您的功能。
您还需要致电bash才能执行函数。
parser() {
echo "GOT: $1"
}
export -f parser
find Projects/ -type f -name '*rb' -exec bash -c 'parser "$0"' {} ;
我建议您使用sed,这是进行文本处理的功能更强大的工具。例如,我想在结尾为" ha"的行之后添加字符串" myparse",我可以像
一样执行此操作# echo "haha" > text1
# echo "hehe" > text2
# echo "heha" > text3
# find . -type f -exec sed '/ha$/s/ha$/ha myparse/' {} ;
haha myparse
heha myparse
hehe
如果您真的想替换文件,而不仅仅是打印到stdout,也可以像
一样执行此操作# find . -type f -exec sed -i '/ha$/s/ha$/ha myparse/' {} ;