関連する字幕を含む動画ファイルがたくさんあります。字幕とビデオをmatroshkaコンテナにマージするbashスクリプトを作成しようとしています。
入力ビデオファイル名は、ソースコンテナに応じて「videoName.mkv」、「videoName.webm」、またはvideoName.mp4です。字幕ファイル名には「videoName.言語Code.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
)。
ループは、および3つのパターンのいずれかに一致する*.mkv
すべての*.webm
名前を繰り返します*.mp4
。これにより、これらのサフィックスと一致することを確認するためにループ変数をテストする必要がなくなります。
にファイル名が与え$video
られたら、ファイル名サフィックス(何でも)を削除して名前部分を抽出します。これは私たちに$name
。
これによりset
パターンを一致させることができます"$name".*.vtt
。このパターンが1つ以上のファイル名と一致する場合、そのファイル名はにあり、$1
一致するファイル名の先頭と末尾を削除して言語部分(パターンのエントリと一致するビット)を抽出します。*
$name.
.vtt
mkvmerge
その後、必要な情報を提供するために電話をかけます。私たちいいえmkvmerge
ファイルがないと呼び出されます.vtt
(あなたのコードがこれを行うようです)。
thing.mp4
また、ファイル名のサフィックスの前に、などの同じ名前の複数のファイルがある場合、これらのファイルは同じ名前()を持つ同じコマンドをthing.mkv
生成します。mkvmerge
-o
substhing.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