如果我在管道中使用此命令,它可以正常工作;
pipeline ... | grep -P '^[^\s]*\s3\s'
但是如果我想将grep设置为变量,如:
var="grep -P '^[^\s]*\s3\s'"
如果我将变量放入管道中;
pipeline ... | $var
没有任何反应,就像没有任何匹配一样。
任何帮助我做错了什么?
答案 0 :(得分:3)
你做错了是试图在变量中存储命令。为简单起见,鲁棒性等命令存储在别名(如果没有参数)或函数(如果参数)中,而不是变量中。在这种情况下:
$ alias foo='grep X'
$ echo "aXb" | foo
aXb
我建议你阅读Chris Johnson ASAP的Shell Scripting Recipes一书来获取shell编程的基础知识,然后是Arnold Robbins的Effective Awk Programming,第4版,当你准备开始编写脚本来操作文本时。
答案 1 :(得分:3)
在Bash中的变量中存储 简单命令的强大方法是使用数组 :
# Store the command names and arguments individually
# in the elements of an *array*.
cmd=( grep -P '^[^\s]*\s3\s' )
# Use the entire array as the command to execute - be sure to
# double-quote ${cmd[@]}.
echo 'before 3 after' | "${cmd[@]}"
相反,如果您的命令不仅仅是简单命令,例如,涉及管道,多个命令,循环,......,定义功能 是正确的方法:
# Define a function encapsulating the command...
myGrep() { grep -P '^[^\s]*\s3\s'; }
# ... and use it:
echo 'before 3 after' | myGrep
为什么您尝试的不起作用
var="grep -P '^[^\s]*\s3\s'"
导致正则表达式周围的单引号成为$var
值的文字,嵌入部分。
当您使用$var
- unquoted - 作为命令时,会发生以下情况:
Bash执行分词,这意味着它通过空格(在特殊变量$var
中定义的字符)将$IFS
的值分解为单词(单独的标记),其中包含默认情况下,空格,制表符和换行符。)
"$var"
- 即,双引号变量引用 - 不是一个解决方案,因为那时整个< / em> string被视为命令 name 。)具体来说,结果是:
grep
-P
'^[^\s]*\s3\s'
- 包括周围的单引号然后将这些单词解释为命令及其参数的名称,并按原样调用。
grep
的模式参数以 literal 单引号开头,匹配不会按预期工作。没有使用eval "$var"
- 不建议出于安全原因 - 你无法说服Bash将嵌入式单引号视为语法元素应该是删除(适当的流程称为报价删除)。
使用数组通过将参数存储在单个元素中并让Bash以"${cmd[@]}"
强大地将它们组合成命令来绕过所有这些问题。