在 grep 中使用简单的正则量词表达式

在 grep 中使用简单的正则量词表达式

有谁知道为什么ls | xargs -n 1 basename | grep -E '[0-9]{1}'不只显示 0-9 之间的单个数字的出现?

例如,如果我有:

touch 1
touch 22
touch 333
touch test_file

如果我跑ls | xargs -n 1 basename | grep -P '[0-9]{1}'

我列出了 1、22 和 333 个文件。

如果我跑ls | xargs -n 1 basename | grep -P '[0-9]{2}'

我列出了 22 和 333 个文件。

我希望 {2} 仅显示 22 文件。

答案1

我认为你期待的事情与正在发生的事情不同的原因是你正在采取

[0-9]{n}

意思是仅匹配 [0-9] 中出现的 n 个字符并丢弃其余的,而它的作用是在 [0-9] 中找到 n 个出现的字符并将其称为匹配。所以在

[0-9]{1}

它会准确地找到任何一次匹配 [0-9] 的内容,因此 1 匹配,然后在检查 22 时,它会在前 2 处停止并认为它是匹配的,而不查看其余的。对于 333 也是如此。如果您指定

[0-9]{2}

它不会匹配 1,而是匹配 22 场比赛,然后是 333 场比赛中的 33 场比赛,所以它会抓住它。

正如 slm 所说,单词边界是这里的关键。您的问题中既有 -P 也有 -E 风格的 grep 正则表达式匹配。您可以将 GNU \< 和 \> 与 -E 一起使用,如下所示:

ls | xargs -n 1 basename | grep -E '\<[0-9]{1}\>'

或 \b 与 -E 或 pcre 匹配 -P 如下

ls | xargs -n 1 basename | grep -P '\b[0-9]{1}\b'

答案2

用于grep -x查找精确匹配,而不是在行内查找匹配。

grep foo查找包含 的行foo,同时grep -x foo查找包含 foo

同样,grep -E '[0-9]{1}'(与 相同grep '[0-9]')查找包含一位数字的行。grep -xE '[0-9]{1}'查找由一位数字组成的行。

使用 GNU grep,您可以使用--color-o选项来查看正在匹配的内容,尽管它会显示所有匹配项。

答案3

这是因为前两个字符与333正则表达式匹配,因此整行匹配。

如果你想避免这种情况,你可以使用:

(^|[^0-9])[0-9]{2}([^0-9]|$)

答案4

如果将示例的内容放入文本文件中,您可以看到为什么grep匹配它:

$ grep -E '[0-9]{1}' file.txt
touch 1
touch 22
touch 333

您可以使用单词边界 ( -w) 来表明grep您只想匹配正则表达式 ( \<REGEX\>) 的单个单词,而不是恰好匹配它的任何字符串:

$ grep -Ew '\<[0-9]{1}\>' file.txt
touch 1

$ grep -Ew '\<[0-9]{2}\>' file.txt
touch 22

$ grep -Ew '\<[0-9]{3}\>' file.txt
touch 333

\<告诉边界在哪里\>grep这会强制grep匹配显式单词(例如 1),但不匹配字符串(例如 11、111 或 aa11aa),因为这些字符串中的正则表达式不包含在单词边界内。

相关内容