匹配包含正则表达式标签的字符串

匹配包含正则表达式标签的字符串

我有一堆带有相关字幕的视频文件。我正在尝试编写一个 bash 脚本,将字幕和视频合并到 matroshka 容器中。

输入视频文件名为“videoName.mkv”、“videoName.webm”或videoName.mp4,具体取决于原始容器。输入字幕文件名为“videoName.languageCode.vtt”。输出视频文件名为“subsvideoName” .mkv"

这是我想出的脚本:

#!/bin/bash

for video in *; do
    if [[ $video =~ \.(mkv|webm|mp4)$ ]]; then
        [[ $video =~ \.(mkv|webm|mp4) ]]
        format=${BASH_REMATCH}
        [[ $video =~ .*[^$format] ]]
        name=${BASH_REMATCH}
        echo $name
        arsubs=()
        for subs in *; do
            echo "$subs"
            if [[ $subs =~ $name.*\.vtt$ ]]; then
                [[ $subs =~ \.[a-zA-Z0-9\-]*\.vtt$ ]]
                lang=$BASH_REMATCH
                [[ $lang =~ [^\.][a-zA-Z0-9\-]*[^\.] ]]
                lang=$BASH_REMATCH
                if [[ $lang =~ [a-z]*[^a-z]+ ]]; then
                    lang=$BASH_REMATCH
                    [[ $lang =~ [a-z]* ]]
                    lang=$BASH_REMATCH
                fi
                arsubs+=(--language 0:$lang)
                arsubs+=("$subs")
            fi
        done
        nameout=subs$name.mkv
        mkvmerge -o "$nameout" "$video" "${arsubs[@]}"
    fi
done

我遇到问题的正则表达式是 [[ $subs =~ $nom.*.vtt$ ]] (第 13 行),如果文件名包含正则表达式标签(例如“+”或“$”),则该正则表达式不匹配。如果文件名不包含此类字符,则脚本运行良好。

我环顾四周,但我能找到的唯一解决方案需要转义有问题的字符,我认为这不能在这里完成。

感谢您的时间。

答案1

你似乎以一种非常迂回的方式来解决这个问题,有太多的正则表达式匹配。

那这个呢?

#!/bin/bash

shopt -s nullglob

for video in *.mkv *.webm *.mp4; do
        name=${video%.*}

        set -- "$name".*.vtt
        if [ -e "$1" ]; then
                lang=${1#$name.}
                lang=${lang%.vtt}

                mkvmerge -o "subs$name.mkv" "$video" --language "0:$lang" "$1"
        fi
done

这假设您想要使用.vtt为给定找到的第一个文件$name(如果有多个.vtt文件,例如对于多种语言)。

该循环遍历与 、 和 三个模式中的任何一个匹配的*.mkv所有*.webm名称*.mp4。这样,您就不必针对这些后缀测试循环变量来确定它是否与其中任何一个匹配。

给定 中的文件名$video,然后通过简单地删除文件名后缀(无论它是什么)来提取名称部分。这给了我们$name.

有了set,我们就可以匹配模式了"$name".*.vtt。如果此模式至少匹配一个文件名,则该文件名将位于 中,我们通过从匹配文件名的前面和末尾删除来提取其中的语言部分(与模式中的$1匹配的位)。*$name..vtt

然后我们打电话mkvmerge提供必要的信息。我们mkvmerge如果没有文件,则调用.vtt(您的代码似乎正在这样做)。

另请注意,如果文件名后缀之前有多个同名文件,例如thing.mp4thing.mkv,则这些文件将产生具有相同名称 ( )mkvmerge的相同命令。-osubsthing.mkv

.vtt您可以通过循环遍历文件,然后选择与文件名相对应的您最感兴趣的视频文件格式来解决此问题.vtt

不过,您在任何时候都不必使用正则表达式来实现这些目的。

以下是考虑.vtt给定名称的所有文件的变体:

#!/bin/bash

shopt -s nullglob

for video in *.mkv *.webm *.mp4; do
        name=${video%.*}

        sub_opts=()
        for sub in "$name".*.vtt; do
                lang=${sub#$name.}
                lang=${lang%.vtt}

                sub_opts+=( --language "0:$lang" "$sub" )
        done

        if [ "${#sub_opts[@]}" -gt 0 ]; then
                mkvmerge -o "subs$name.mkv" "$video" "${sub_opts[@]}"
        fi
done

相关内容