在循环中获取grep命令的输出

时间:2017-12-03 09:01:51

标签: bash function shell grep

我有一个包含此搜索的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命令结果输出到函数

3 个答案:

答案 0 :(得分:1)

只有shell才能执行某个功能。您需要在bash -c中使用find才能执行它。这也是您需要导出函数的原因,以便新进程可以看到它。

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等发送到你要处理的函数。 不会逐个发送每一行,因此您需要遍历函数中的行。如果文件中没有出现你的正则表达式,它将仍然用空输入调用你的函数!

这对您来说可能不是最佳解决方案,所以让我们尝试在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

此方法运行正常,逐个处理每一行。您还需要使用此方法导出您的函数。但是你必须要关心一些可能让你感到惊讶的事情。

管道中的每个命令都在它自己的子shell中执行,而parser函数或while中的任何变量赋值一般都会在从子shell返回后丢失。如果您正在编写脚本,简单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示例中,您将遇到相同的行为,并且您的变量分配也将丢失。

答案 1 :(得分:0)

您需要导出您的功能。

您还需要调用bash来执行该功能。

parser() {
  echo "GOT: $1"
}
export -f parser

find Projects/ -type f -name '*rb' -exec bash -c 'parser "$0"' {} \;

答案 2 :(得分:0)

我建议你使用sed,这是做文本处理的更强大的工具。 例如,我想添加字符串&#34; myparse&#34;在以&#34; ha&#34;结尾的行之后,我可以这样做

# 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/' {} \;