5

我正在尝试做一个小的 bash 脚本,它会清理我喜欢的一些电视节目的下载剧集的文件和文件夹名称。它们通常看起来像“[www.Speed.Cd] - Some.Show.S07E14.720p.HDTV.X264-SOMEONE”,我基本上只是想去掉那个 speedcd 广告位。

在 BASH 中使用正则表达式匹配来删除 www.Speed.Cd、空格和破折号很容易,但对于我来说,我无法弄清楚如何在要匹配的字符列表中包含括号。[- [] 不起作用,[- \[]、[- \\[]、[- \\\[] 或我要删除的括号前面的任何数量的转义字符也不起作用。

这是我到目前为止所得到的:

[[ "$newfile" =~ ^(.*)([- \[]*(www\.torrenting\.com|spastikustv|www\.speed\.cd|moviesp2p\.com)[- \]]*)(.*)$ ]] &&
    newfile="${BASH_REMATCH[1]}${BASH_REMATCH[4]}"

但它打破了括号。

有任何想法吗?

TIA,丹尼尔:)

编辑:我可能应该注意到我正在使用“shopt -s nocasematch”来确保不区分大小写的匹配,以防万一你想知道:)

编辑2:感谢所有做出贡献的人。我不能 100% 确定哪个答案是“正确的”,因为我的陈述有几个问题。实际上,最准确的答案只是对jw013发布的我的问题的评论,但我当时没有得到它,因为我还不明白空格应该被转义。我选择了 aefxx,因为那个人基本上说的是一样的,但有解释:) 也希望在 ormaaj 的答案上加上一个正确的答案标记,因为他发现我的表达有更严重的问题。

无论如何,我在上面使用的方法,试图匹配和提取部分以保留和留下不需要的部分真的不是很优雅,并且不会捕捉所有情况,甚至不是像“Some.Show.S07E14”这样非常简单的东西.720p.HDTV.X264-某人 - [ www.Speed.Cd ]”。相反,我重写了它以匹配并仅提取不需要的部分,然后对原始字符串上的部分进行字符串替换,就像这样(循环是在有多个品牌的情况下):

# Remove common torrent site brandings, including surrounding spaces, brackets, etc.:
while [[ "$newfile" =~ ([[\ {\(-]*(www\.)?(torrentday\.com|torrenting\.com|spastikustv|speed\.cd|moviesp2p\.com|publichd\.org|publichd|scenetime\.com|kingdom-release)[]\ }\)-]*) ]]; do
    newfile=${newfile//"${BASH_REMATCH[1]}"/}
done
4

4 回答 4

7

好的,这是我第一次听说=~运营商,但这是我通过反复试验发现的:

if [[ $newfile =~ ^(.*)([-[:space:][]*(what|ever)[][:space:]-]*)(.*)$ ]] 
                          ^^^^^^^^^^              ^^^^^^^^^^

看起来很奇怪,但实际上确实有效(刚刚测试过)。

编辑
Linux 手册页 regex(7) 中的引用:

要在列表中包含文字 ],请将其设为第一个字符(可能的 ^ 之后)。要包含文字 -,请将其设为第一个或最后一个字符,或范围的第二个端点。要将文字 aq-aq 用作范围的第一个端点,请将其括在“[.”中。和“.]”使其成为整理元素(见下文)。除了这些和一些使用 aq[aq 的组合(见下一段)之外,所有其他特殊字符,包括 aq\aq,在括号表达式中都失去了它们的特殊意义。

于 2012-04-16T22:36:19.220 回答
4

每当您执行正则表达式时,将正则表达式放入变量中是 Bash 版本之间最兼容的,即使您确实设法避开了将它们直接放入测试表达式的所有陷阱。http://mywiki.wooledge.org/BashPitfalls#if_.5B.5B_.24foo_.3D.2BAH4_.27some_RE.27_.5D.5D

您当前的正则表达式看起来像您正在尝试选择匹配左括号之前的任何内容。我猜您实际上是在尝试从以下内容中保存例如 3 和 4:

$ shopt -s nocasematch
$ newfile='[ www.Speed.Cd ] - Some.Show.S07E14.720p.HDTV.X264-SOMEONE'
$ re='^.*[-[:space:][]*(www\.torrenting\.com|spastikustv|www\.speed\.cd|moviesp2p\.com)[][:space:]-]*(.*)$'
$ [[ $newfile =~ $re ]]
$ declare -p BASH_REMATCH
declare -ar BASH_REMATCH='([0]="[ www.Speed.Cd ] - Some.Show.S07E14.720p.HDTV.X264-SOMEONE" [1]="www.Speed.Cd" [2]="Some.Show.S07E14.720p.HDTV.X264-SOMEONE")'
于 2012-04-16T21:59:10.663 回答
1

基本问题很简单,即使不是很明显。
BASH REGEX完全不受保护(来自 shell),并且不能被​双引号​<strong>”保护。这意味着每个文字空间(和制表符等)都必须受到 baskslash \... 故事结尾的保护。剩下的只是让你的正则表达式满足你的需要的一个例子。

另一件事;在范围方括号构造内(在本例中与空格一起), 使用[\ []and[]\ ]来匹配 [and 。]

例子:

newfile="[ ]"
[[ "$newfile" =~ ^[\ []\ []\ ]$ ]] &&
    echo YES ||
    echo NO
于 2012-04-17T00:08:56.510 回答
0

您可以尝试这样的事情(尽管您不是 100% 清楚您要过滤哪些情况:

newfile="[ www.Speed.Cd ] - Some.Show.S07E14.720p.HDTV.X264-SOMEONE"

if [[ $newfile =~ ^(.*)([^a-zA-Z0-9.]*\[.*\][^a-zA-Z0-9.]*)(.*)$ ]]; then 
    newfile="${BASH_REMATCH[1]}${BASH_REMATCH[3]}"
fi

echo $newfile
# Some.Show.S07E14.720p.HDTV.X264-SOMEONE

它只是剥离 之外的任何非alnum(和点)字符[],以及内部的任何内容[]

于 2012-04-16T21:36:45.473 回答