Bash:简单的方法来传递一个“原始”string到grep?
从命令行使用grep
时,不能input“raw”string,因为某些字符需要转义而不被视为文字。 例如:
$ grep '(hello|bye)' # WON'T MATCH 'hello' $ grep '\(hello\|bye\)' # GOOD, BUT QUICKLY BECOMES UNREADABLE
我正在使用printf
来自动转义string:
$ printf '%q' '(some|group)\n' \(some\|group\)\\n
这会产生一个bash转义的string版本,并使用反引号,这可以很容易地传递给一个grep调用:
$ grep `printf '%q' '(a|b|c)'`
但是,显然这并不意味着:输出中的某些字符不会被转义,有些字符是不必要的。 例如:
$ printf '%q' '(^#)' \(\^#\)
传递给grep
时, ^
字符不应该被转义。
是否有一个cli工具,需要一个原始的string,并返回一个可以直接用作grep模式的string的bash转义版本 ? 如果没有,我怎么能在纯粹的bash中实现这个呢?
如果您试图让grep
使用扩展的正则expression式语法,那么做的方法是使用grep -E
(又名egrep
)。 你也应该知道grep -F
(又名fgrep
),在GNU Coreutils的更新版本中, grep -P
。
背景:原始的grep
只有一小部分正则expression式, 这是Ken Thompson最初的正则expression式实现。 随后开发了一个带有扩展库的新版本,出于兼容性原因,获得了不同的名称。 使用GNU grep
,只有一个二进制文件,它理解传统的基本RE语法(如果调用grep
,而ERE(如果调用egrep
。 egrep
中的一些构造可以通过使用反斜杠转义来引入特殊的意义。
随后,Perl编程语言更进一步扩展了forms化; 这个正则expression式似乎是大多数新手错误地期望grep
支持的。 用grep -P
,它确实; 但是在所有平台上还没有得到广泛的支持。
所以,在grep
,以下字符有特殊含义: ^$[]*.\
在egrep
,下列字符也有特殊含义:( ()|+?{}
。 (重复的大括号不在原始的egrep
)。分组括号还可以对\1
, \2
等进行反向引用。
在许多版本的grep
,可以通过在egrep
特殊项之前加一个反斜杠来获得egrep
行为。 还有像\<\>
这样的特殊序列。
在Perl中,引入了大量额外的转义,例如\w
\s
\d
。 在Perl 5中,正则expression式的工具大大扩展了,而非贪婪匹配*?
+?
非分组括号(?:...)
,向前看,向后看,等等。
…话虽如此,如果你真的想在不调用任何外部进程的情况下将egrep
正则expression式转换为grep
正则expression式,请为每个egrep
特殊字符尝试${regex/pattern/substitution}
; 但要认识到这不能正确处理字符类,否定字符类或反斜杠转义。
如果你想search一个确切的string,
grep -F '(some|group)\n' ...
-F
告诉grep
按照原样处理这个模式,而不是作为正则expression式的解释。
(这通常也可以作为fgrep
。)
当我用grep -E用户提供的string时,我用这个来逃避它们
ere_quote() { sed 's/[]\.|$(){}?+*^]/\\&/g' <<< "$*" }
示例运行
ere_quote ' \ $ [ ] ( ) { } | ^ . ? + *' # output # \\ \$ \[ \] \( \) \{ \} \| \^ \. \? \+ \*
这样你可以安全地在你的正则expression式中插入带引号的string。
例如,如果您想查找以用户内容开始的每一行,并且用户提供有趣的string为*。
userdata=".*" grep -E "^$(ere_quote "$userdata")" <<< ".*hello" # if you have colors in grep you'll see only ".*" in red
很有用! 只是想指出,我相信它有一个小错误(请纠正我,如果我错了):
代替:
sed 's/[] ...
是: sed 's/[[] ...
为了检测“ [
”字符
我认为以前的答案是不完整的,因为他们错过了一个重要的事情,即string以破折号( – )开头。 所以虽然这不起作用:
echo "ABC" | grep -F "-B-"
这个将会:
echo "ABC" | grep -F -- "-B-"