当它们来自命令行时,我们如何egrep特殊字符?

时间:2019-01-24 09:07:48

标签: bash grep

为清楚起见,我举一个例子。

假设我们要用bash脚本编写一个技术熟练的egrep,这意味着这个人不知道如何转义特殊字符,他只会传递他想找到的内容。

例如,当他想在文章中找到时,他使用

./myEgrep it's myArticle

代替

./myEgrep it\'s myArticle**

我们如何在脚本中处理此问题?基本上,egrep无法像人类一样被赋予并理解包含特殊字符的字符串。最难的部分是如何将 $ 1 包装在脚本内的 Xgrep $ 1 $ myArticle 中。我尝试了fgrep,它也不行。

2 个答案:

答案 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

因此,您的用户执行上述脚本,并可以输入您允许他们输入的任何命令,并可以包含他们喜欢的任何字符。