我有一个文件,其中包含 a(i)%b(j)%c 形式的变量,其中 a、b 和 c 始终相同,但索引 i 和 j 可能不同(包括多个字符)。因此,我尝试使用 grep 来查找这些变量的实例,但成功取决于我是否在搜索字符串周围包含引号,并且我试图理解为什么存在差异。我开始搜索单字符索引的情况:
(1)grep a\(.\)\%b\(.\)\%c file
按预期工作
(2)grep 'a\(.\)\%b\(.\)\%c' file
没有匹配项
(3)grep "a\(.\)\%b\(.\)\%c" file
没有匹配项
然后(让自己更加困惑!),我尝试包括多字符索引的可能性:
(4)grep a\(.*\)\%b\(.*\)\%c file
不起作用 - zsh :未找到匹配项:a(.)%b(.)%C
(5)grep 'a\(.*\)\%b\(.*\)\%c' file
作品
(6)grep "a\(.*\)\%b\(.*\)\%c" file
作品
有人可以解释一下每种情况下发生了什么吗?在情况 (4) 中,由于星号的原因,shell (zsh) 看起来正在做一些不同的事情,但我不确定它在做什么。为什么(1)、(5)和(6)有效,但(2)和(3)不起作用,这让我特别困惑。
谢谢!
答案1
您必须区分 shell 转义和grep
转义。
基本正则表达式(BRE;如果grep
不带选项使用则使用该-E
表达式)将(
,)
和|
视为普通字符。序列\(
和\|
具有特殊含义。
如果没有引号,shell 会将反斜杠视为转义字符并将其删除,即grep
看不到它。使用引号会看到反斜杠,因此和grep
的含义会发生变化。(
|
对于扩展正则表达式 ( grep -E
) ,则相反:(
和|
是特殊的,您需要在它们之前加一个 bashslash 才能将它们作为普通字符处理。