【问题标题】:how linux grep -oP print the pattern onlylinux grep -oP 如何仅打印模式
【发布时间】:2021-05-15 09:06:24
【问题描述】:
# cat a.file
123123abc file2
274efcc4d8a0e8f61397be46bd4bfa37  file1
321  file1

# file="file1"
# grep -m 1 -oP "\K([\w]+) +$file" a.file
274efcc4d8a0e8f61397be46bd4bfa37  file1

如何使用参数file1 行获得输出274efcc4d8a0e8f61397be46bd4bfa37,并且只使用grep 命令而不使用| 或其他类似awk 的命令?

grep -P 是否有一些其他参数只打印匹配模式\K([\w]+),例如结果是274efcc4d8a0e8f61397be46bd4bfa37?或者是否有任何实现仅使用grep 获得结果。

【问题讨论】:

    标签: regex linux grep pcre


    【解决方案1】:
    $ file='file1'
    $ grep -m1 -oP '\w+(?= +'"$file"'$)' a.file
    274efcc4d8a0e8f61397be46bd4bfa37
    

    (?=regexp) 是一个积极的前瞻结构,它可以帮助您定义一个断言,而不会将它作为匹配部分的一部分。有关环视的更多信息,请参阅Reference - What does this regex mean?

    我还将'\w+(?= +'"$file"'$)' 并排放置,这样只有shell 变量在双引号下。此处使用$ 锚来避免部分匹配,例如file1file1afile11。如果您的文件名可以包含正则表达式元字符(例如:.),那么您需要使用 '\w+(?= +\Q'"$file"'\E$)' 来匹配文件名。


    不知道为什么你不想在这里使用awk,它非常适合这个任务。字符串比较很方便,可以避免处理正则表达式转义。

    awk -v f="$file" '$2==f{print $1; exit}'
    

    【讨论】:

      【解决方案2】:

      你误用了\K,它会丢弃匹配的文本捕获直到当前时刻,它在模式的开头没有用。 +file1 是消费模式,它将作为匹配部分返回。

      使用非消耗模式:

      grep -m 1 -oP "\w+(?=\s+$file\b)" a.file
      

      regex proof\b 将不允许匹配 file10

      解释

      --------------------------------------------------------------------------------
        \w+                      word characters (a-z, A-Z, 0-9, _) (1 or
                                 more times (matching the most amount
                                 possible))
      --------------------------------------------------------------------------------
        (?=                      look ahead to see if there is:
      --------------------------------------------------------------------------------
          \s+                      whitespace (\n, \r, \t, \f, and " ") (1
                                   or more times (matching the most amount
                                   possible))
      --------------------------------------------------------------------------------
          file1                    'file1'
      --------------------------------------------------------------------------------
          \b                       the boundary between a word char (\w)
                                   and something that is not a word char
      --------------------------------------------------------------------------------
        )                        end of look-ahead
      

      【讨论】: