linux grep -oP 如何只打印模式

how linux grep -oP print the pattern only

# 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 获得结果。

$ file='file1'
$ grep -m1 -oP '\w+(?= +'"$file"'$)' a.file
274efcc4d8a0e8f61397be46bd4bfa37

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

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


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

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

你误用了\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