如何在文件中为此(两件事)grep?


37

我有一个带有“ then”和“ there”的文件。

我可以

$ grep "then " x.x
x and then some
x and then some
x and then some
x and then some

我可以

$ grep "there " x.x
If there is no blob none some will be created

如何在一次操作中同时搜索两者?我试过了

$ grep (then|there) x.x

-bash:意外令牌'('附近的语法错误

grep "(then|there)" x.x
durrantm.../code
# (Nothing)

Answers:


53

您需要将表达式放在引号中。您收到的错误是bash解释(为特殊字符的结果。

另外,您需要告诉grep使用扩展的正则表达式。

$ grep -E '(then|there)' x.x

如果没有扩展正则表达式,你必须逃离|()。请注意,我们在这里使用单引号。Bash特别处理双引号内的反斜杠。

$ grep '\(then\|there\)' x.x

在这种情况下,不需要分组。

$ grep 'then\|there' x.x

像这样的事情将是必要的:

$ grep 'the\(n\|re\)' x.x

3
另请参阅grep $'then\nthere'grep -e then -e there。请注意,这\|不是BRE中的标准。其余的是。特别是在双引号猛砸对待反斜杠只有之前"$\ `和换行符。
斯特凡Chazelas

1
目的是x.x什么?
alex

7

只是一个快速的附录,大多数版本都有一个名为egrep的命令,该命令只是带有-E的grep。我个人更喜欢打字

egrep "i(Pod|Pad|Phone)" access.log

比使用grep -E


2

(或至少是我的)手册页中“常规表达”下记录的内容实际上是用于扩展的正则表达式;

grep理解正则表达式语法的三种不同版本:“基本”,“扩展”和“ perl”。在GNU grep中,基本语法和扩展语法之间的可用功能没有区别。在其他实现中,基本正则表达式的功能较弱。 以下描述适用于扩展的正则表达式;基本正则表达式的差异将在后面总结。

但是grep默认情况下不使用它们-您需要进行-E切换:

grep "(then|there)" x.x

因为(再次从手册页):

基本与扩展正则表达式

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

因此,您还可以使用:

grep "then\|there" x.x

由于在这种情况下括号是多余的。


0

Bash的优雅简洁似乎在庞大的手册页中迷失了。

除了上述出色的解决方案之外,我还想为您提供有关bash如何解析和解释语句的速查表。然后,使用此路线图,我将分析发问者提出的示例,以帮助您更好地理解它们为什么无法按预期运行。


注意:Shell脚本行直接使用。输入的输入行首先进行历史扩展。

每个bash行首先被标记化,或者换句话说,被切成所谓的标记。(令牌化发生在所有其他扩展之前,包括大括号,代字号,参数,命令,算术,过程,单词拆分和文件名扩展。)

此处的令牌表示输入行的一部分由以下特殊元字符之一分隔(定界):

space,  - White space...
tab, 
newline,

‘<’,    - Redirection & piping...
‘|’, 
‘>’
‘&’,    - And/Both < | > | >>  .or.  &<file descriptor>

‘;’,    - Command termination

‘(’,    - Subshell, closed by -     ‘)’

Bash使用许多其他特殊字符,但是只有这10个特殊字符会产生初始标记。

但是,由于有时有时必须在令牌中使用这些元字符,因此需要一种方法来消除其特殊含义。这称为转义。逸出的,(即,通过引用的一个或多个字符的字符串要么完成'xx..'"xx.."),或者通过用反斜线,(即前缀个别字符\x)。(它比这复杂一点,因为引号也需要加引号,并且双引号不能引出所有内容,但是这种简化现在才有用。)

不要将bash引用与引用文本字符串的思想混淆,就像其他语言一样。bash中引号之间的内容不是字符串,而是输入行中转义了元字符的部分,因此它们不分隔标记。

请注意,'和和之间有一个重要区别",但这是另一天的区别。

其余未转义的元字符将成为令牌分隔符。

例如,

$ echo "x"'y'\g
xyg

$ echo "<"'|'\>
<|>

$ echo x\; echo y
x; echo y

在第一个示例中,由空格分隔符产生了两个标记:echoxyz

同样在第二个示例中。

在第三个例子中,分号被转义,所以有一个空格分隔符,产生4个令牌echox;echo,和y。然后,第一个令牌将作为命令运行,并将接下来的三个令牌作为输入。注意第二个echo没有执行。


要记住的重要一点是,庆典首先查找转义字符('",和\),然后查找转义元字符分隔符,按照这个顺序。

如果不进行转义,则这10个特殊字符将用作token分隔符。其中一些还具有其他含义,但首先,它们是标记定界符。


grep期望什么

另外,在上述的grep的例子中需要这些令牌,grepstringfilename

这个问题的第一次尝试是:

$ grep(then | there)xx

在这种情况下()|是未转义元字符等用于将输入划分成这些令牌:grep(then|there),和x.x。grep的希望看到grepthen|therex.x

问题的第二尝试是:

grep“(then | there)” xx

这将标记化grep(then|there)x.x。如果将grep换成echo,则可以看到以下内容:

回显“(然后|那里)” xx
(然后|那里)xx

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.