bash 使用正则表达式仅查找文件名开头的数字
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/14304731/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Finding only numbers at the beginning of a filename with regex
提问by mac389
I'm (a regex noob) trying to find only the files in a directory that begin with numbers and not strings.
我(正则表达式菜鸟)试图仅在目录中查找以数字而不是字符串开头的文件。
My regex is
我的正则表达式是
.*/^\d+\w+[A][D][0-5][0-9].mat
(The end of the file name has the letters AD and then numbers from 0-54 before the MAT extension. I include ./because I am going to pass this to findin bash.)
(文件名的末尾有字母 AD,然后是 MAT 扩展名之前的 0-54 数字。我包括在内./是因为我要将其传递给findin bash。)
However, this returns false for both files like
但是,这对于两个文件都返回 false,例如
./times_121312_going_down_AD33.mat
and
和
./121312_going_down_AD33.mat
What am I doing wrong?
我究竟做错了什么?
回答by Michel Feldheim
Here's a working example with find
这是一个带有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
\dand \wdon't work in POSIX regular expressions, you could use [:digit:]tho
\d并且\w不适用于POSIX 正则表达式,您可以使用[:digit:]tho
The regular expression explained
正则表达式解释
.*repeat any character except\n, zero or more times/match character '/' literally[0-9]+repeat any char in 0 to 9, one or more times_match character '_' literally.*repeat any character except\n, zero or more timesAmatch character 'A' literallyDmatch character 'D' literally[0-5]Match any char in 0 to 5[0-9]Match any char in 0 to 9\.match '.' literallymmatch 'm' literallyamatch 'a' literallytmatch 't' literally$end of string
.*重复任何字符,除了\n,零次或多次/字面上匹配字符“/”[0-9]+重复 0 到 9 中的任何字符,一次或多次_字面上匹配字符“_”.*重复任何字符,除了\n,零次或多次A字面上匹配字符“A”D字面上匹配字符“D”[0-5]匹配 0 到 5 中的任何字符[0-9]匹配 0 到 9 中的任何字符\.比赛 '。' 字面上地m从字面上匹配“m”a字面上匹配“a”t从字面上匹配“t”$字符串的结尾
If you just want to match all files beginning with an integer you can break it down to .*/[0-9]which would also match ./12/test.tmpand ./12_not_a_mat_file.txt
如果您只想匹配以整数开头的所有文件,您可以将其分解为.*/[0-9]也匹配./12/test.tmp和./12_not_a_mat_file.txt
回答by Adam Sznajder
Your regexp: .*/\d+\w+[A][D][0-5][0-9]\.mat(there shouldn't be ^and you have to remember to escape a dot .because without \it simply means "any character".
你的正则表达式:(.*/\d+\w+[A][D][0-5][0-9]\.mat不应该有^,你必须记住转义一个点,.因为没有\它只是意味着“任何字符”。
You can always try this assuming that you [A][D][0-5][0-9]part was not important: .*/\d\w+\.mat
假设你的[A][D][0-5][0-9]部分不重要,你总是可以尝试这个:.*/\d\w+\.mat
回答by shellter
The \detc notation you're using is from perl (and maybe other places too), but not supported by the bashcommand line.
\d您使用的etc 符号来自 perl(也可能是其他地方),但bash命令行不支持。
You'll need to use
你需要使用
./[0-9][0-9][0-9][0-9][0-9]*
To match a 5 digit + "anything else" value.
匹配 5 位数字 +“其他任何”值。
If need to match for 1-n possible digits at the front, you'll need to "OR" together those possibilities. A case statement can help sort that out and make it a little more managable, i.e.
如果需要在前面匹配 1-n 个可能的数字,您需要将这些可能性“或”在一起。case 语句可以帮助解决这个问题并使其更易于管理,即
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
Note that you have to test for the longer matches first, as the shorter match will also match the longer strings.
请注意,您必须首先测试较长的匹配项,因为较短的匹配项也将匹配较长的字符串。
There are other solutions depending on your needs, but this will not require starting a subprocess, so it's pretty efficient.
根据您的需要,还有其他解决方案,但这不需要启动子流程,因此非常有效。
IHTH
IHTH
回答by Josh Cartwright
If you are running a new enough bash, you can express what you are looking for using an exglob.
如果您正在运行一个足够新的 bash,您可以使用 exglob 表达您正在寻找的内容。
shopt -s extglob
for f in ./+([0-9])*AD[0-5][0-9].mat; do
# do something with "$f"
done
Note, the above is not a recursive search, for bash-only recursive search, you'll need a version of bash which also supports globstar:
请注意,以上不是递归搜索,对于仅 bash 递归搜索,您需要一个也支持 globstar 的 bash 版本:
shopt -s extglob globstar
for f in ./**/+([0-9])*AD[0-5][0-9].mat; do
# do something with "$f"
done
Alternatively, a recursive search can be done with GNU find's -regexoption.
或者,可以使用 GNU find 的-regex选项进行递归搜索。

