【问题标题】:Finding only numbers at the beginning of a filename with regex使用正则表达式仅查找文件名开头的数字
【发布时间】:2013-01-14 03:50:57
【问题描述】:

我(一个正则表达式菜鸟)试图只查找目录中以数字而不是字符串开头的文件。

我的正则表达式是

 .*/^\d+\w+[A][D][0-5][0-9].mat

(文件名的末尾有字母 AD,然后是 MAT 扩展名之前的 0-54 数字。我包括 ./,因为我将把它传递给 bash 中的 find。)

但是,这对于两个文件都返回 false

./times_121312_going_down_AD33.mat

./121312_going_down_AD33.mat

我做错了什么?

【问题讨论】:

  • 您希望表达式中的 ^ 做什么?在 [] 之外,它匹配行首的空字符串,匹配 .*/ 后,^ 无法匹配。
  • 哦,我以为它表明它后面的表达式应该匹配字符串的开头。

标签: regex bash


【解决方案1】:

这是一个使用 find 的工作示例

$ ls -l *.mat
-rw-r--r-- 1 root root 0 Jan 13 15:09 121312_going_down_AD33.mat
-rw-r--r-- 1 root root 0 Jan 13 15:09 times_121312_going_down_AD33.mat

$ find . -type f -regex '.*/[0-9]+_.*AD[0-5][0-9]\.mat$'
./121312_going_down_AD33.mat

\d\wPOSIX regular expressions 中不起作用,您可以使用[:digit:] tho

正则表达式解释

  • .* 重复任何字符,除了\n,零次或多次
  • / 匹配字符 '/' 字面意思
  • [0-9]+ 将任何字符重复 0 到 9 次,一次或多次
  • _ 从字面上匹配字符“_”
  • .* 重复任何字符,除了\n,零次或多次
  • A 匹配字符“A”
  • D 匹配字符“D”
  • [0-5]匹配0到5中的任意字符
  • [0-9]匹配0到9中的任意字符
  • \. 匹配“。”字面意思
  • m 匹配 'm' 字面意思
  • a 匹配 'a' 字面意思
  • t 匹配 't' 字面意思
  • $ 字符串结束

如果您只想匹配以整数开头的所有文件,可以将其分解为 .*/[0-9],这也将匹配 ./12/test.tmp./12_not_a_mat_file.txt

【讨论】:

  • 感谢提醒,\d\w 在 POSIX 正则表达式中都不起作用。因为我将此命令传递给在集群上运行的 MATLAB,所以这很重要。
【解决方案2】:

你的正则表达式:.*/\d+\w+[A][D][0-5][0-9]\.mat(不应该有^,你必须记住转义一个点.,因为没有\,它只是意味着“任何字符”。

假设您的 [A][D][0-5][0-9] 部分不重要,您可以随时尝试此操作:.*/\d\w+\.mat

【讨论】:

    【解决方案3】:

    您使用的 \d 等表示法来自 perl(也可能来自其他地方),但 bash 命令行不支持。

    你需要使用

     ./[0-9][0-9][0-9][0-9][0-9]*
    

    匹配一个 5 位数字 +“任何其他”值。

    如果需要匹配前面的 1-n 个可能的数字,您需要将这些可能性“或”在一起。案例陈述可以帮助解决这个问题并使其更易于管理,即

     case ${fileName} in
      ./[0-9][0-9][0-9][0-9]*|./[0-9][0-9][0-9][0-9][0-9]*) echo "4 or 5 nums at front" ;;
      ./[0-9]*|./[0-9][0-9]*|./[0-9][0-9][0-9]* ) echo "up to 3 nums at front" ;;
      #-------^-------------^--- note the '|' regex OR
     esac
    

    请注意,您必须先测试较长的匹配项,因为较短的匹配项也会匹配较长的字符串。

    根据您的需要还有其他解决方案,但这不需要启动子流程,因此非常有效。

    IHTH

    【讨论】:

      【解决方案4】:

      如果您正在运行一个足够新的 bash,您可以使用 exglob 表达您正在寻找的内容。

      shopt -s extglob
      for f in ./+([0-9])*AD[0-5][0-9].mat; do
          # do something with "$f"
      done
      

      注意,以上不是递归搜索,对于仅 bash 的递归搜索,您需要一个也支持 globstar 的 bash 版本:

      shopt -s extglob globstar
      for f in ./**/+([0-9])*AD[0-5][0-9].mat; do
          # do something with "$f"
      done
      

      或者,可以使用 GNU find 的 -regex 选项进行递归搜索。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-11-29
        • 1970-01-01
        • 1970-01-01
        • 2016-07-04
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多