我试图找到一个仅匹配数字文件扩展名的 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]##
##
相当于+
扩展正则表达式运算符。
与ksh
或bash -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]