我想创建一个可以自动执行以下操作的脚本:
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中使用的字符串,但我不知道如何继续,如果这是解决问题的最佳方法。我将不胜感激任何有关如何编程的建议。
答案 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