【问题标题】:Using the star sign in grep在 grep 中使用星号
【发布时间】:2010-11-07 08:17:28
【问题描述】:

我正在尝试在 linux/bash 的特定文件中搜索子字符串“abc”

所以我这样做:

grep '*abc*' myFile

它什么也不返回。

但如果我这样做:

grep 'abc' myFile

它正确返回匹配项。

现在,这对我来说不是问题。但是,如果我想用 grep 查找更复杂的字符串,比如

*abc * def *

我将如何使用 grep 来完成它?

【问题讨论】:

  • grep 本身在大多数平台上不支持通配符。您必须使用 egrep 才能使用通配符。 Shell 有不同的语法。 shell 中的“*”是。在 egrep 中,它是一个操作符,它说“0 到许多以前的实体”。在 grep 中,它只是一个普通字符。
  • @PanCrit: * 在 grep 和 egrep 中的含义相同:它是一个 量词,表示前面的原子的零个或多个。这与 shell 使用的 通配符 是完全不同的概念。
  • @AlanMoore 感谢您的更新。我不知道这是什么时候改变的,但是现代的grep 支持大多数基本的正则表达式是正确的。过去,您必须使用 egrep 才能获得比扁平字符串更多的东西,但我看到 grep 已经进化了。

标签: regex bash grep


【解决方案1】:

星号只是一个repetition operator,但你需要告诉它你重复了什么。 /*abc*/ 匹配包含 ab 和零个或多个 c 的字符串(因为第二个 * 在 c 上;第一个没有意义,因为它没有什么可重复的)。如果你想匹配任何东西,你需要说.*——点表示任何字符(within certain guidelines)。如果你只想匹配 abc,你可以说grep 'abc' myFile。对于更复杂的匹配,您需要使用 .* -- grep 'abc.*def' myFile 将匹配一个包含 abc 后跟 def 的字符串,中间有一些可选的内容。

根据评论更新:

正则表达式中的* 与控制台中的 * 不完全相同。在控制台中,* 是glob construct 的一部分,只是充当通配符(例如ls *.log 将列出所有以.log 结尾的文件)。但是,在正则表达式中,* 是修饰符,这意味着它仅适用于其前面的字符或组。如果想让正则表达式中的 * 充当通配符,则需要使用.*,如前所述——点是通配符,星号在修改点时表示找到一个或多个点; IE。找到一个或多个任意字符。

【讨论】:

  • 我认为提问者对shell通配符和正则表达式之间的区别感到困惑。我还怀疑更复杂的表达式是: grep 'abc .* def' (至少存在一个空格 - 可能是我写的两个)。
  • 其实提问者好像不明白 'abc' 和 '^abc$' 不是一回事 :-D
  • 是的,我对 glob 和完整的正则表达式感到困惑。我使用不带点的 * 表示匹配外壳上的任何内容。
  • grep * 表示“0或更多”,grep默认为贪婪。请注意,在 grep basic 正则表达式中,元字符 ?+{|() 失去了它们的特殊含义。更多信息:grep regexps
【解决方案2】:

点字符表示匹配任何字符,因此.* 表示任何字符出现零次或多次。您可能的意思是使用.* 而不仅仅是*

【讨论】:

  • 点是一个元字符,可以接受除换行以外的任何字符。
【解决方案3】:

“星号”只有在它前面有东西时才有意义。如果没有该工具(在这种情况下为 grep),则可能会将其视为错误。例如:

'*xyz'    is meaningless
'a*xyz'   means zero or more occurrences of 'a' followed by xyz

【讨论】:

  • * 不是没有意义的;它只是没有它通常的含义(重复),而是意味着“我是明星”。它将匹配包含星号后跟 x、y 和 z 的行。
  • @Jonathan 这取决于工具。
【解决方案4】:

使用 grep -P - 支持 Perl 风格的正则表达式。

grep -P "abc.*def" myfile

【讨论】:

    【解决方案5】:

    您尝试的表达式,例如在 Linux 中的 shell 命令行上工作的表达式,称为“glob”。 Glob 表达式不完整regular expressions,这是 grep 用来指定要查找的字符串的。 Here 是(旧的,小的)关于差异的帖子。 glob 表达式(如“ls *”)由 shell 本身解释。

    可以从 glob 转换为 RE,但您通常需要在脑海中这样做。

    【讨论】:

    • 如果它被 shell 解析,它只是一个 glob。由于他将搜索字符串保留在单引号内,因此 shell 不处理该字符串,并在 argv 中将其原封不动地传递给 grep。
    【解决方案6】:

    您没有使用正则表达式,因此您选择的 grep 变体应该是 fgrep,它将按照您的预期运行。

    【讨论】:

    • fgrep 现已弃用,应使用 grep -f 代替。
    • 那是“grep -F”。好的 ol' fgrep 可能会被“弃用”,但他们不会在我还活着的时候把它拿走。
    【解决方案7】:

    尝试 grep -E 以获得扩展的正则表达式支持

    还可以看看:

    The grep man page

    【讨论】:

      【解决方案8】:

      这对我有用:

      grep ".*${expr}" - 带有双引号,前面是点。 其中 ${expr} 是您在行尾需要的任何字符串。

      所以在你的情况下:

      grep ".*abc.*" myFile
      

      标准 unix grep。

      【讨论】:

        【解决方案9】:

        '*' 用作前一项的修饰符。所以 'abc*def' 搜索 'ab' 后跟 0 个或多个 'c' 后跟 'def'。

        您可能想要的是 'abc.*def',它搜索 'abc' 后跟任意数量的字符,然后是 'def'。

        【讨论】:

          【解决方案10】:

          这可能是您正在寻找的答案:

          grep abc MyFile | grep def
          

          唯一的事情是......它将输出“def”在“abc”之前或之后的行

          【讨论】:

            猜你喜欢
            • 2014-01-30
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2018-11-19
            • 2013-12-26
            • 2014-11-05
            相关资源
            最近更新 更多