我正在尝试列出所有 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]
之间查找单个数字(或点)。即它会找到,但不会找到。)G
T
1G
1.2G
或者使用例如 awk:
du -h . | awk '$1 ~ /[GT]/'
(真的不需要寻找数字。我们知道它们就在那里。)