我正在尝试下面的代码并希望得到结果为 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 -E
egrep
egrep '(....)'
相同的规则适用于 sed。一个简单的 sed 理解基本的正则表达式,因此您需要转义来捕获组:或者您可以在with或switchsed 's/\(....\)\(...\)/\2/'
中启用扩展的正则表达式支持(取决于 sed 实现):sed
-E
-r
sed -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)。