POSIX glob -- 如何匹配一个或多个 [:digit:]

5
我想遍历foo.log和它的日志轮换兄弟foo.1.gzfoo.2.gz,从最新到最旧,使用不会被存在foo.bar欺骗的代码。
高兴的是,logrotate的命名使得最新到最旧和按字母排序是相同的顺序。
我的原始尝试是for f in $(ls -t foo.*) ; do ...shellcheckIterating over ls output is fragile. Use globs. [SC2045]。此外,这段代码匹配了不需要的foo.bar
但是如何使用glob模式匹配任意数量的数字?(或者这不受支持吗?)我只知道如何显式地列出每个数字位数。例如,以下处理1位和2位数字并正确排除foo.1bar.gz,但无法处理foo.123.gz(并且我没有做正确的事情来引起glob匹配!) for f in foo.log foo.[[:digit:]].gz foo.[[:digit:]][[:digit:]].gz; do ... 我可以假设没有人保留100个以上的日志轮换兄弟,但我不想这样做。
寻找符合POSIX的解决方案...
编辑:logrotate conf会压缩某些文件,并且不会压缩其他文件。因此,并非所有兄弟都以.gz结尾。
2个回答

5

一个glob模式不是正则表达式。有关语法,请参见glob(7)。

没有glob模式可以匹配一系列数字。您可以使用foo.[0-9]*.gz来接近。如果它选择了一些您不想要的名称,则可以使用正则表达式进行过滤,例如:

echo foo.[0-9]*.* | tr ' ' \\n | grep -E '[.][0-9]+([.]gz)?$' 

考虑到您所提供的约束条件,您可能需要使用通配符模式,并依赖于 shell 进行排序。 您可以使用 sort 检查您的 shell 是否按排序顺序呈现通配符模式的文件名:

echo foo.[0-9]*.gz | tr \  \\n | sort -c

但是,如果您不是非常严格的话,解析ls -t的输出也是可以的。来自shellcheck的指导是很好的建议:许多人似乎想要解析ls的输出,当一个简单的glob也能实现时,并且依赖ls在不同系统上表现相同会引发错误。尽管如此,您只需要请求ls按时间排序文件名,从而产生单列输出。任何其他操作都更容易出错。


啊,但是foo.*.gz匹配了foo.bar.log.1.gz,这是foo.bar.log的第一个被旋转的日志,与foo.log无关,这就是我尝试使用[[:digit:]]的原因… - user1011471
更接近了。但是,(1)有时日志轮换的兄弟文件没有被压缩,因此它们不会以.gz结尾。我应该在问题中提到这一点作为可能性。包括foo.[0-9]*打开了匹配foo.0a的可能性,这将是我的代码中的一个错误。此外,(2)原始文件名会匹配foo.0a.gz,这在日志目录中显然是一个不太可能的文件名。使用[[:digit:]]列出可能性可以处理这个问题,在我的情况下可能值得这样做,但这样我处理的是一位数字和两位数字,而不是n位数字。(撇开日志轮换不谈,我仍然想知道是否有一种方法来处理从1到n位数字的glob匹配。) - user1011471
回答你的问题,没有通配符模式可以匹配一系列数字。我会使用通配符来找到一组好的候选项,如果需要进一步筛选,就将该组通过正则表达式进行处理。这样既高效又灵活。 - James K. Lowden
如果您在答案中包含这个,我可以接受它。 - user1011471
完成。我认为现在的答案已经包含了我们在评论中的讨论。 - James K. Lowden

-1

由于[:digit:]表示[0-9],如果您想匹配一个或多个数字,请与“一个或多个”运算符一起使用。

结果:+([0-9])

需要测试全局模式吗? DigitOceans在此处发布了一个不错的工具。 https://www.digitalocean.com/community/tools/glob

祝好运!


4
这并非由 POSIX 标准要求的,正如 OP 所请求的那样。 - Sean Bright
1
对我来说,我得到了“-bash:语法错误,附近的标记`('” - Levi Uzodike
Globs 没有“一个或多个”运算符。 - shrewmouse
1
这需要执行 shopt -s extglob 命令(也称为扩展通配符)。 - Vinny

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接