Linux grep 与正则表达式问题

Linux grep 与正则表达式问题

我正在尝试下面的代码并希望得到结果为 0 (即$? -eq 0),但由于某种原因它总是失败:

echo "INBOUND_PATH|/tmp" | grep -E '^\(INBOUND_PATH\)\|\(.*\)$';

echo $?

我想创建反向引用的原因是因为如果字符串格式有效,那么我将使用以下命令剪切目录:

g_inboundDir=grep -E 's/^\(INBOUND_PATH\)\|(.*)$/\2';

答案1

将差距和所有答案放在一起,并查看 grep ( man grep) 的手册页,我们有两种主要的正则表达式:基本正则表达式和扩展正则表达式。

根据 man grep :

基本正则表达式与扩展正则表达式
在基本正则表达式中,元字符 ?、+、{、|、( 和 ) 失去了它们的特殊含义;而是使用反斜杠版本 \?、+、{、\|、( 和 )。

换句话说,如果您使用或不需要转义括号,则可以使用转义的()类似 或单个 grep 捕获组:grep \(....\)grep -Eegrepegrep '(....)'

相同的规则适用于 sed。一个简单的 sed 理解基本的正则表达式,因此您需要转义来捕获组:或者您可以在with或switchsed 's/\(....\)\(...\)/\2/'中启用扩展的正则表达式支持(取决于 sed 实现):sed-E-rsed -E 's/(...)(...)/\2/'

因此,以下所有命令均有效:

$ echo "INBOUND_PATH|/tmp" | grep '^\(INBOUND_PATH\)|\(.*\)$';echo $?
INBOUND_PATH|/tmp
0

$ echo "INBOUND_PATH|/tmp" | egrep '(INBOUND_PATH)\|(.*)$';echo $?
INBOUND_PATH|/tmp
0

$ echo "INBOUND_PATH|/tmp" | sed 's/^\(INBOUND_PATH\)|\(.*$\)/\2/'
/tmp

$ echo "INBOUND_PATH|/tmp" | sed -E 's/(INBOUND_PATH)\|(.*)$/\2/'
/tmp

注意不同正则表达式中特殊符号的相反处理。

|例如,请参阅上面命令中管道符号的处理:
在基本正则表达式 (BRE) 中:
您不需要转义管道符号来匹配文字管道符号。
BRE 中的转义管道符号将被视为 OR 运算符(它意外地适用于您的情况)。

类似地,在 BRE 中,您不需要转义括号( )来匹配文字括号,但需要转义括号来捕获组。

在扩展正则表达式 (ERE) 中:
您需要对管道符号进行转义才能按字面匹配,因为默认情况下,在 ERE 中管道符号被视为 OR 运算符(与 BRE 相比,处理相反)

类似地,在 ERE 中,您需要转义括号以匹配文字括号(,因为默认情况下,ERE 中的括号用于捕获组。

答案2

字符串的基本检查不必那么复杂:
echo "INBOUND_PATH|/tmp" | grep -q '^INBOUND_PATH|.*$'

我假设你的意思是第二个是 sed,而不是 grep:
g_inboundDir=$(echo "INBOUND_PATH|/tmp" | sed 's/^\(INBOUND_PATH\)|\(.*$\)/\2/')

注意缺少-E。我还修复了丢失的尾随 /。

答案3

您要添加 -E 这是扩展的正则表达式

-E, --extended-regexp 将 PATTERN 解释为扩展正则表达式(ERE,见下文)。

并且还在逃避它。不需要。

$ echo "INBOUND_PATH|/tmp" | grep -E '^(INBOUND_PATH)\|(\/.*)'; echo $?
INBOUND_PATH|/tmp
0

另一方面,您可以使用埃格雷普具有相同的效果(没有-E)。

相关内容