如何制作一个脚本来对文件进行多次grep?

时间:2016-03-29 04:25:08

标签: bash

我想创建一个可以自动执行以下操作的脚本:

 grep 'string1' file.txt | grep 'string2' | grep 'string3' ... | grep 'stringN'

这个想法是脚本可以像这样运行:

myScript.sh file.txt string1 string2 string3 ... stringN

并且脚本必须返回包含所有字符串的file.txt的所有行。

例如,如果file.txt看起来像这样:

hello world 
hello world run 
hello planet world 

我可以这样做一个grep:

grep hello file.txt | grep world

我得到了:

hello world 
hello world run 
hello planet world

我想创建一个自动生成此脚本的脚本,并将未定义数量的字符串作为参数。

我发现很难实现这一点,因为字符串的数量可以变化。首先,我尝试在args中创建一个名为myScript.sh的数组:

 #!/bin/bash
 args=("$@")

用于存储参数。我知道${args[0]}将是我的file.txt,其余的是我需要在不同的greps中使用的字符串,但我不知道如何继续,如果这是解决问题的最佳方法。我将不胜感激任何有关如何编程的建议。

5 个答案:

答案 0 :(得分:2)

/** * This class was generated by the JAX-WS RI. * JAX-WS RI 2.1.3-hudson-390- * Generated source version: 2.1 * */ 能够通过单个流程完美地完成此任务,并避免这些sed恶作剧。生成的脚本实际上非常简单。

eval

我们为每个表达式生成一行#!/bin/sh file=$1 shift printf '\\?%s?!d\n' "$@" | sed -f - "$file" 脚本;如果找不到表达式(sed),我们删除(!)此输入行,并从下一行开始。

这假定您的d接受sed作为-的参数来从标准输入读取脚本。这不是完全便携的;如果这是一个问题,您可能需要将生成的脚本存储在临时文件中。

这使用-f作为内部正则表达式分隔符。如果你需要其中一个模式中的文字?,你需要反斜杠 - 逃避它。在一般情况下,创建一个脚本来查找不在任何搜索表达式中的替代分隔符也许是可能的,但在那时,我将转向适当的脚本语言(Python将是我的偏好)而不是

答案 1 :(得分:1)

您可以生成操作模式并将其保存在变量中:

pattern="$(printf 'grep %s file.txt' "$1"; printf ' | grep %s' "${@:2}" ; printf '\n')"

然后

eval "$pattern"

示例:

% cat file.txt                                                          
foo bar
bar spam
egg

% grep_gen () { pattern="$(printf 'grep %s file.txt' "$1"; printf ' | grep %s' "${@:2}" ; printf '\n')"; eval "$pattern" ;}

% grep_gen foo bar                           
foo bar

答案 2 :(得分:1)

您可以在循环中创建命令,然后使用eval对其进行评估。 这是使用cat,因此您可以对所有grep进行分组。

#! /bin/bash

file="$1"
shift
args=( "$@" )


cmd="cat '$file'"
for a in "${args[@]}"
do
    cmd+=' | '
    cmd+="grep '$a'"
done

eval $cmd

答案 3 :(得分:1)

无评估的替代方案:

#!/bin/bash

temp1="$(mktemp)"
temp2="$(mktemp)"

grep "$2" "$1" > temp1
for arg in "${@:3}"; do
    grep "$arg" temp1 > temp2
    mv temp2 temp1
done

cat temp1
rm temp1

mktemp生成一个具有唯一名称的临时文件并返回其名称;它应该广泛使用。

然后循环为每个参数执行grep,并为下一个循环重命名第二个临时文件。

答案 4 :(得分:1)

这是Diego Torres Milano代码的优化以及我原来问题的答案:

$git push