这是我的第一个问题,所以我希望我的标题和格式不会太乱。
我有一堆文件,我的客户以这种形式发送给我:
Name.Of.Chapter.021x212.The.Actual.Title.Of.the.Chapter.DOC.NAME-Some.stuff.Here.ext
我需要的是正则表达式输出:
212章节的实际标题
我不会特别使用任何脚本语言;它是通过支持正则表达式的应用程序批量重命名文件(已经“保留”扩展名)。
到目前为止,我所能做到的只有:
/.*x(\d+)\.(.*?)\.[A-Z]{3}.*/ -->REPLACE: $1 $2
(捕获前面带有“x”的数字之前的所有内容,“x”后的组号,将所有内容分组,直到满足3位大写单词,然后捕获后面的所有内容) <登记/> 这让我回来了:
212 The.Actual.Title.Of.the.Chapter
看到结果之后,我想到了这样的事情:
/.*x(\d+)\.([^.]*?)\.[A-Z]{3}.*/ -->REPLACE: $1 $2
(将第二组更改为“捕获一切这不是一个点 ...”)将按预期工作。 相反,整个正则表达式无法完全匹配。
我错过了什么?
TIA
CIA
麦酒
答案 0 :(得分:2)
.*x(\d+)\.
匹配Name.Of.Chapter.021x212.
\.[A-Z]{3}.*
匹配.DOC.NAME-Some.stuff.Here.ext
但([^.]*?)
与The.Actual.Title.Of.the.Chapter
不匹配,因为此正则表达式根本不允许任何句号。
答案 1 :(得分:1)
因为你在Mac上,你可以使用shell
$ s="Name.Of.Chapter.021x212.The.Actual.Title.Of.the.Chapter.DOC.NAME-Some.stuff.Here.ext"
$ echo ${s#*x}
212.The.Actual.Title.Of.the.Chapter.DOC.NAME-Some.stuff.Here.ext
$ t=${s#*x}
$ echo ${t%.[A-Z][A-Z][A-Z].*}
212.The.Actual.Title.Of.the.Chapter
或者如果您更喜欢sed,例如
echo $filename | sed 's|.[^x]*x||;s/\.[A-Z][A-Z][A-Z].*//'
用于处理多个文件
for file in *.ext
do
newfile=${file#*x}
newfile=${newfile%.[A-Z][A-Z][A-Z].*}
# or
# newfile=$(echo $file | sed 's|.[^x]*x||;s/\.[A-Z][A-Z][A-Z].*//')
mv "$file" "$newfile"
done
答案 2 :(得分:1)
您的问题“如何在匹配过程中删除点?”答案是“你做不到。”唯一的方法是通过第二步处理匹配结果,正如其他人所说的那样。但我认为还有一个需要解决的基本问题,即“匹配给定输入的正则表达式意味着什么?”
当正则表达式描述该字符串的任何子字符串时,通常会说它与字符串匹配。如果您想确保正则表达式描述整个字符串,您需要添加开头(^
)和结束($
)锚点:
/^.*x(\d+)\.(.*?)\.[A-Z]{3}.*$/
但在你的情况下,你不需要描述整个字符串;如果你在任何一端摆脱.*
,它也会为你提供服务:
/x(\d+)\.(.*?)\.[A-Z]{3}/
我建议您不要习惯在开头和结尾使用.*
“填充”正则表达式。特别是前导.*
可以以意想不到的方式改变正则表达式的行为。例如,输入字符串中有两个位置x(\d+)\.
可以匹配,您的“真实”匹配将从第二个开始。此外,如果它不是以^
或\A
为基础,则前导.*
可能会降低整个正则表达式的效率。
我之前说过“通常”,因为有些工具会在开头(Python的match()
)或两端(Java的matches()
)自动“锚定”匹配,但这种情况非常罕见。 * nix系统上提供的大多数shell和命令行工具都以传统方式定义了一个正则表达式匹配,但是为了以防万一,最好说出你正在使用的工具。
最后,关于词汇的一两句话。 (\d+)
中的括号会使匹配的字符捕获,而不是分组。许多正则表达式都支持(?:\d+)
形式的非捕获括号,仅用于分组。任何包含在整体匹配中的文本,无论是否被捕获,都被认为是消费(不是捕获)。您在问题中使用“捕获”和“群组”这两个词的方式可以保证在任何假设您知道自己在说什么的人中造成最大的混淆。 :d
如果您尚未阅读,请查看此excellent tutorial。