如何将文件名解析为组件

时间:2013-06-12 20:01:11

标签: regex macos bash

我收集了一些vhs转移的电视剧集,所有这些剧集的标题都是根据格式"显示名称SXXEYY剧集Title.mp4"我想向他们添加iTunes mp4标签。我有一种方法可以从命令行执行此标记,但是希望改进我的shell脚本功能并编写可以自动执行此操作的内容。

我认为bash脚本会为我做这个。理想情况下,正确编写的正则表达式会查看文件名并返回Show,Season,Episode和Title,并允许我将这些结果传递给bash脚本中的标记工具。正确编写的正则表达式将返回BASH_REMATCH [1] .. [4]这四个数据。

在这里我被困住了 - 我似乎无法让我的正则表达式序列表现出来。

我对语法的理解向我提出了如下表达式:

Regex for Show Name: ^(?:(?! S[0-9][0-9]).)*
Regex for Season Number: (?<=S)(.*)(?=E)
Regex for Episode Number: (?<=S[0-9][0-9]E)..
Regex for Episode Title: (?<=S[0-9][0-9]E[0-9][0-9] )(.*)(?=.(mp4))

应该产生可接受的结果。但到目前为止,我甚至无法通过bash来回复任何争论。我显然遗漏了一些东西,但是

#!/bin.bash

for filename in "Cop Rock S01E03 Happy Mudder's Day.mp4" ; do
    if [[ "$filename" =~ (?<=S[0-9][0-9]E[0-9][0-9] )(.*)(?=.(mp4)) ]]; then
        echo  "${BASH_REMATCH[1]}${BASH_REMATCH[2]}"
    fi
done

应该返回一个剧集名称和mp4后缀,但到目前为止还没有结果。

我也对其他解决方案持开放态度,例如使用sed,但我以前从未使用过sed而且几乎不能拼写它,所以学习曲线可能很陡峭。

如果有人能够指出我所犯的错误,我将非常感激。它是bash 3.2; =〜运算符确实有效。

2 个答案:

答案 0 :(得分:5)

您正在尝试使用Perl样式的正则表达式(特别是零宽度lookbehind断言),bash无法理解。请尝试以下方法:

regex="(.*) S([0-9]{2})E([0-9]{2}) (.*)\.mp4"
for filename in "Cop Rock S01E03 Happy Mudder's Day.mp4" ; do
    if [[ "$filename" =~ $regex ]]; then
        echo "Show: ${BASH_REMATCH[1]}"
        echo "Season: ${BASH_REMATCH[2]}"
        echo "Episode: ${BASH_REMATCH[3]}"
        echo "Title: ${BASH_REMATCH[4]}"
    fi
done

答案 1 :(得分:0)

我知道自从上一次关于这个问题的活动开始已经过去了1。5年,但我一直在寻找同样的事情并且回答了这个问题。我稍微调整了一下答案以便更通用(允许所有小写文件名,点代替空格,不同的扩展名和多个文件名)所以我想与你分享我的更新:

#!/bin/bash

regex="(.*)[ .][sS]([0-9]{2})[eE]([0-9]{2})[ .](.*)\.(mp4|mkv)"
for filename in ${*}
do
    if [[ "${filename}" =~ ${regex} ]]; then
        echo "Show: ${BASH_REMATCH[1]}"
        echo "Season: ${BASH_REMATCH[2]}"
        echo "Episode: ${BASH_REMATCH[3]}"
        echo "Title: ${BASH_REMATCH[4]}"
    fi
done

如果将其复制到shell文件中并使其可执行,则可以更普遍地使用它。