为清楚起见,我举一个例子。
假设我们要用bash脚本编写一个技术熟练的egrep,这意味着这个人不知道如何转义特殊字符,他只会传递他想找到的内容。
例如,当他想在文章中找到是时,他使用
./myEgrep it's myArticle
代替
./myEgrep it\'s myArticle**
我们如何在脚本中处理此问题?基本上,egrep无法像人类一样被赋予并理解包含特殊字符的字符串。最难的部分是如何将 $ 1 包装在脚本内的 Xgrep $ 1 $ myArticle 中。我尝试了fgrep,它也不行。
答案 0 :(得分:2)
您的问题是单引号由shell或bash处理,并且实际上使命令停止执行,直到用户键入另一个单引号为止。 如果整个短语都由用户用双引号引起来,那么他们将不需要转义单引号或任何空格,即:
./myEgrep "it's" myArticle
我认为这很容易向用户解释,甚至不那么精明的用户。
然后在脚本文件中,您需要再次将参数用双引号引起来:
Xgrep "$1" "$myArticle"
脚本中的最佳实践是几乎总是将参数用双引号引起来,因为它保留了变量内的空格。
当然,这就剩下了用户如何从命令行插入双引号的问题。对于您来说,简单的答案是让他们使用单引号将双引号引起来,但对于他们而言可能不是;如果他们想混合引号怎么办?
另一种选择是让您处理输入并将空格转换为任意长度的正则表达式,并为所有引号(包括unicode开/闭引号)将单引号转换为正则表达式?再次,易于向用户解释。任何其他方案,您将重新发明转义码。
答案 1 :(得分:0)
'
不是唯一的问题。如果用户键入./myEgrep foo .* bar
或./myEgrep foo $(rm *) bar
(不要尝试!)怎么办?当有人从外壳调用工具时,它们在外壳中,因此外壳语法和语义适用。
如果希望他们能够使用任何参数来调用命令,并且使该调用的含义与Shell中的含义有所不同,那么您需要编写一个包装器工具来为其设置受限/非Shell环境在其中工作,例如:
#!/bin/env bash
function myEgrep() {
local re="$1"
grep -E "$re" wherever
}
while IFS= read -r line; do
cmd="${line%% *}"
args="${line#* }"
case $cmd in
myEgrep ) myEgrep "$args" ;;
esac
done
因此,您的用户执行上述脚本,并可以输入您允许他们输入的任何命令,并可以包含他们喜欢的任何字符。