【问题标题】:Match file names using Linux Shell regex使用 Linux Shell 正则表达式匹配文件名
【发布时间】:2015-02-18 18:29:43
【问题描述】:

我需要一种方法来匹配目录中的文件名。

例如我有三个文件:

CAt_DoG_ZebRa.TXT
MOUSE_lion_deer_BIRD.TXT
fIsh_biRD_LION.TXT

无论如何我都不是正则表达式专家,但是我之前在 SnapLogic 和 Pentaho 中使用过类似的东西:

(?i).*(?=.*bird)(?=.*lion).*.TXT

上面将匹配所有包含单词“bird”和“lion”的文件名,忽略大小写,单词的顺序无关紧要。很强大!所以它会匹配这两个:

MOUSE_lion_deer_BIRD.TXT    
fIsh_biRD_LION.TXT

我结合 find 和 grep 尝试了上述的许多变体,但无济于事。例如:

find . -regex ".*/(?i).*(?=.*bird)(?=.*lion).*.TXT"

上面的查找不匹配任何内容。

谁能推荐一种方法来做到这一点?

【问题讨论】:

  • 所以你想匹配包含狮子或鸟的文件?即Cat_dog_zebra不会被包括在内?
  • 包含狮子和鸟的。是的 Cat_dog_zebra 不会被包括在内。
  • Find 的-regex 在我知道的find 的任何实现中默认不是PCRE(您在此处编写代码的语法)。在 GNU 系统上,如果你看到手册页,你会看到一个 -regextype 让你选择你想要的语法。
  • 也就是说,我完全不知道您为什么需要正则表达式。如果常规 glob 无法做到这一点,那么 extglobs 可以——以及 bash 4 或 zsh,你有一个足够强大的 globing 语法,即使在递归情况下也根本不需要 find

标签: regex linux shell


【解决方案1】:
shopt -s globstar   # enable recursive globs
shopt -s nocaseglob # make globs case-insensitive
for file in ./**/*bird*lion*.txt; do
  echo "found: $file"
done

...或者,如果您不关心这些单词之间的顺序:

shopt -s globstar   # enable recursive globs
shopt -s nocaseglob # make globs case-insensitive
shopt -s extglob    # enable extended globbing syntax
for file in ./**/*@(bird*lion|lion*bird)*.txt; do
  echo "found: $file"
done

【讨论】:

  • 他想匹配一个只有两个单词的文件。这不符合他的要求。
  • @BrianStephens,已编辑;现在可以了(如果文件多次包含两个单词之一,则可能存在包含重复结果的错误)。
  • @BrianStephens,...而且,现在,连那个 bug 都没有了。
  • 这应该清楚地捕捉到它。不错。
  • @CharlesDuffy 我将您的代码放入脚本并尝试执行,但出现了一些错误:./match_script.sh: line 1: shopt: globstar: invalid shell option name found: ./ **/*@(birdlion|lionbird)*.txt ./match_script.sh: line 7: /home/mdmdusr: is a directory –
【解决方案2】:
# ls
asdafsdfdBirdasfdfd.txt      dasdbirdbfdgdlionb.txt       fgdfLionqweBirdaqw.txt   
# ls | /usr/gnu/bin/grep -i -E '.*(bird.*lion|lion.*bird).*\.txt'
dasdbirdbfdgdlionb.txt
fgdfLionqweBirdaqw.txt

一个技巧:当你使用前瞻或后视写一些正则表达式时,怀疑它,要么改变另一种写法,要么考虑正则表达式是否适合解决这个问题。

【讨论】:

  • 这里唯一有点不幸的是,读者可能不清楚ls 的使用只是示例,而不是良好实践的示例。 (参见mywiki.wooledge.org/ParsingLs 讨论如何在脚本中使用ls 导致错误)。
  • 环视是必要的,因为它强制它匹配两个单词,而你的却不匹配。
  • @CharlesDuffy 是的。这很糟糕。
【解决方案3】:

首先, 不支持 PCRE 正则表达式引擎,因此这是您的问题的解决方案,(递归):

 bash -c "shopt -s globstar; perl -lne 'print if /i.*bird/i and /i.*lion/i' **"

此解决方案适用于所有匹配鸟和狮子的文件名,以任何顺序

【讨论】:

  • 他想匹配一个只有两个单词的文件。您需要在第一个解决方案中将 OR 更改为 AND。在您的第二个解决方案中,将正则表达式改回他所拥有的,它应该可以工作。
猜你喜欢
  • 1970-01-01
  • 2020-10-09
  • 1970-01-01
  • 1970-01-01
  • 2020-05-30
  • 2016-06-18
相关资源
最近更新 更多