grep
从命令行使用时,将不能输入“原始”的字符串,由于某些字符需要转义到不会被视为文字。 例如:
$ grep '(hello|bye)' # WON'T MATCH 'hello'
$ grep '\(hello\|bye\)' # GOOD, BUT QUICKLY BECOMES UNREADABLE
我用printf
来自动转义字符串:
$ printf '%q' '(some|group)\n'
\(some\|group\)\\n
这将产生串的一个bash转义版本,并使用反引号,这可以很容易地传递给grep的呼叫:
$ grep `printf '%q' '(a|b|c)'`
但是,它显然不是意味着这样的:在输出一些字符不会被转义,有些是不必要如此。 例如:
$ printf '%q' '(^#)'
\(\^#\)
该^
传递到时字符不应该逃脱grep
。
是否有一个命令行工具,它需要一个原始字符串,并返回可直接用作使用grep模式字符串的一个bash转义版本 ? 我怎样才能在纯bash中实现这一点,如果不是?
如果您正在试图将grep
使用扩展正则表达式语法,做到这一点的方法是使用grep -E
(又名egrep
)。 你也应该知道grep -F
(又名fgrep
),在GNU Coreutils的,较新版本grep -P
。
背景:原来grep
有一个相当小的集合regex操作符的; 这是肯·汤普森的原正则表达式的实现。 新版本具有扩展的曲目,后来发展以及对兼容性的原因,有一个不同的名称。 随着GNU grep
,只有一个二进制文件,如果调用作为理解传统,基本语法RE grep
,和ERE如果援引作为egrep
。 从一些结构egrep
是可用grep
用一个反斜杠逃逸引进特殊的意义。
随后,Perl的编程语言,甚至进一步扩展的形式主义; 此正则表达式方言似乎是大多数新人错误地期待grep
,也支持。 随着grep -P
,它; 但这还没有得到广泛支持的所有平台。
所以,在grep
,以下字符有特殊含义: ^$[]*.\
在egrep
,以下字符也有特殊的意义: ()|+?{}
(用于重复的括号都不在原始egrep
。)该分组括号也使反向引用与\1
, \2
等
在许多版本grep
,你可以得到egrep
通过把一个反斜杠之前的行为egrep
特价商品。 也有像特殊序列\<\>
在Perl中,一个巨大的类似附加逃逸数\w
\s
\d
进行了介绍。 Perl 5中,正则表达式设施被大大延长,与非贪婪匹配*?
+?
等,非分组圆括号(?:...)
向前看符号,lookbehinds等。
......话说回来,如果你真的想要转换egrep
正则表达式grep
正则表达式,而不调用任何外部的过程中 ,尽量${regex/pattern/substitution}
每个的egrep
特殊字符; 但我们也承认这种不处理的字符类,否定的字符类或反斜线正确逃逸。
如果你要搜索一个确切的字符串,
grep -F '(some|group)\n' ...
-F
告诉grep
为IS治疗模式,没有解释的正则表达式。
(这往往是可作为fgrep
为好。)
当我使用grep -E利用用户提供的字符串我逃脱他们本
ere_quote() {
sed 's/[]\.|$(){}?+*^]/\\&/g' <<< "$*"
}
例如运行
ere_quote ' \ $ [ ] ( ) { } | ^ . ? + *'
# output
# \\ \$ \[ \] \( \) \{ \} \| \^ \. \? \+ \*
这样,您就可以安全地插入您的正则表达式中的引号的字符串。
例如,如果你想找到的每一行开始与用户的内容,以向用户提供有趣的字符串作为*。
userdata=".*"
grep -E -- "^$(ere_quote "$userdata")" <<< ".*hello"
# if you have colors in grep you'll see only ".*" in red
我认为,以前的答案是不完整的,因为他们错过了一个重要的事情,即与划线开头的字符串( - )。 因此,尽管这将无法工作:
echo "A-B-C" | grep -F "-B-"
这一次将:
echo "A-B-C" | grep -F -- "-B-"