仅匹配数字文件扩展名

仅匹配数字文件扩展名

我试图找到一个仅匹配数字文件扩展名的 UNIX 模式。例如,它将匹配

  • 文件.1
  • 文件.2
  • 文件1.1
  • 5文件2.52
  • 文件.25938

等等,但不会匹配

  • 文件1.0.ext
  • 文件4.csv
  • 6文件5.5.2.ext
  • 文件.1s
  • 文件.s134

我以为这很容易,但我似乎无法得到它 - 我已经尝试过

  • *.[0-9]* 匹配 file1.0.csv
  • *.[0.9]*/> 不匹配任何内容

那里的专家知道我错过了什么吗?我认为 /> 匹配在单词的末尾。

编辑-澄清:我正在使用使用unix shell样式通配符的模块在python中编码,所以我只能访问所述通配符

答案1

zsh

echo file.<->

<-><x-y>是like的特殊形式<1-100>,但不受限制地匹配任何十进制正整数(任何非空的十进制数字序列)。或者使用以下extendedglob选项:

echo file.[0-9]##

##相当于+扩展正则表达式运算符。

kshbash -O extglob(或在shopt -s extglob之内bash)或zsh -o kshglob(或setopt kshglob在 之内zsh)之后:

echo file.+([0-9])

同样,+(x)就像 ERE x+

ksh93还可以在其 glob 中使用 ERE:

echo ~(E).*\.[0-9]+$

.*这里并不是绝对必要的,只是如果没有它,~(E)\.[0-9]+$也会匹配隐藏文件)

标准 glob 没有等效项。他们所拥有的只是:

  • *匹配任意数量的字符
  • ?匹配任何单个字符
  • [criteria]匹配一个匹配的字符标准

您需要对列表进行后过滤,例如:

set -- *.*[0-9]
for i do
  case ${i##*.} in
    (*[!0-9]*) ;;
    (*) set -- "$@" "$i"
  esac
  shift
done
echo "$@"

也就是说,从包含 a 并以数字结尾的文件名列表中.,排除最后一个部分.包含非数字的文件名。

答案2

在 bash 中(如果$f包含要检查的文件名):

[[ "${f##*.}"  == +([0-9]) ]] && echo "Yes" || echo "No"

其中"${f##*.}"选择最后一个扩展名(最后一个点之后),
并且+([0-9])是仅匹配数字的扩展正则表达式。

处理文件名列表(内部infile)的示例脚本可能是:

#!/bin/bash
while read f; do
    printf 'file %-15s ----> %7s ==> ' "$f" "${f##*.}"
    if     [[ "${f##*.}"  == +([0-9]) ]]
    then   echo "Yes"
    else   echo "No"
    fi
done <"infile"

哪个输出:

file file.1          ---->       1 ==> Yes
file file.2          ---->       2 ==> Yes
file file1.1         ---->       1 ==> Yes
file 5file2.52       ---->      52 ==> Yes
file file.25938      ---->   25938 ==> Yes
file NOT             ---->     NOT ==> No
file file1.0.ext     ---->     ext ==> No
file file4.csv       ---->     csv ==> No
file 6file5.5.2.ext  ---->     ext ==> No
file file.1s         ---->      1s ==> No

使用 (UNIX) 更简单的 shell 需要克服的主要障碍是找到能够理解和执行(扩展)正则表达式的实用程序。

您可以尝试使用“扩展正则表达式” sed

[ "$(echo "${f##*.}" | sed -nE 's/^([0-9]+)$/\1/p')" ] && echo "Yes" || echo "No"

或“基本正则表达式”,也在 sed 中:

[ "$(echo "${f##*.}" | sed -n 's/^\([0-9]\{1,\}\)$/\1/p')" ] && echo "Yes" || echo "No"

或者expr(您可能需要更改\+\{1,\}Solaris 和其他操作系统):

expr "${f##*.}" : '^\([0-9]\+\)$' >/dev/null && echo "Yes" || echo "No"

甚至awk

[ $( echo "${f##*.}" | awk '/^[0-9]+$/' ) ] && echo "Yes" || echo "No"

答案3

蟒蛇匹配您想要使用的模块将给定文件“glob”类型参数转换为 python 正则表达式(re),但它没有按照我希望的方式处理“+”运算符:它似乎被 re.escape() 转义(查看我系统上 python 2.6 中 fnmatch 的源代码)

最后,

fnmatch.filter(['file.007'], '*.[0-9]+')

不是正如我们所期望的那样工作,尽管

fnmatch.filter(['file.7'], '*.[0-9]')

确实给出了匹配。

相似地

 fnmatch.filter(['file.007'], '*.[0-9]{1,}')

不行。

答案4

你的文件以数字结尾,所以只需使用 *[0-9]

相关内容