我想了解如何缩短正则表达式

我想了解如何缩短正则表达式

我正在尝试列出所有 1GB 或更大的目录。我知道我可以使用ncdu,但目前,我只是想了解如何缩短正则表达式......

我找到了这个命令,du -h . | grep '[0-9\.]\+G'但我不明白它是如何工作的。

我尝试用我知道正则表达式的方式来编写它,这就是我想出的:
du -h . | grep '[0-9]\+\.*[0-9]*G

我认为第一个命令查找 0 到 9 以及后面的句点,表示\+一个或多个;所以我认为所有的结果没有点应该被排除在外,但事实并非如此。

第一个命令不应该是这样的吗? grep '[0-9\.]*G'

谢谢。

答案1

嗯,[...]是一个括号组,它匹配其中列出的任何单个字符,遵循范围(在某种程度上取决于区域设置)。[0-9\.]匹配从零到九的任何数字、反斜杠或点。他们可能在那里添加了反斜杠,因为他们认为点需要转义,但括号组内的情况并非如此。

在标准基本正则表达式 (BRE) 中,\+未定义,因此该正则表达式实际上是无效的。在 GNU 系统中,它的工作方式类似于+扩展正则表达式 (ERE),并且匹配前面的一个或多个。在其他系统中,它可能会做其他事情。只G匹配文字G

这里没有理由使用 GNU 特定的表达式,因为我们可以将其重写为标准 ERE 并告诉 grep 使用它而不是 BRE。那可能是

grep -E '[0-9.]+G'

它将匹配至少一个数字或点,后跟一个 G。

我认为第一个命令会查找 0 到 9 以及后面的句点

不,括号表达式内没有顺序。[xyz.]是相同的[z.yx]。如果是[0-9]\.,那么它将查找后跟一个点的任何单个数字。 (这里,点需要转义。)

第一个命令不应该是这样的吗?grep '[0-9\.]*G'

这将使数字(或点)成为可选的,并且将匹配任何带有G.其实,原文中的“一个或多个”也是不必要的;由于表达式在开始时没有锚定到任何内容,[0-9.]G因此也会隐式接受任意数量的数字(或点)。 (即123G它会匹配3G并且 grep 仍然会打印整行。)

[0-9]可以匹配的字符不仅仅是0123456789,如果还有其他字符沿着数字排序,这取决于区域设置的排序顺序。)


du请注意,对于包含目录大小和名称的输出,grep 还将匹配1G路径名中包含 eg 的任何行。此外,如果du可以打印以 TB 等为单位的大小,它会错过大小类似的行1.2T。为了避免这种情况,您需要将表达式锚定到行的开头并至少添加T

du -h . | grep -E '^[0-9.]+[GT]'

(这需要+, 因为只会在行的开头和或^[0-9.][GT]之间查找单个数字(或点)。即它会找到,但不会找到。)GT1G1.2G

或者使用例如 awk:

du -h . | awk '$1 ~ /[GT]/'

(真的不需要寻找数字。我们知道它们就在那里。)

相关内容