BASH_REMATCH

障害

bash正規表現(regexp)パタンマッチにはglobalマッチがない*1

対策

whileループで実現できました。

#! /usr/bin/sh

find . -type f -path "*.ts" | {
    while read f
    do
	echo "$f"
	subject="$f"
	pattern='@([a-zA-Z]+)=?([^\/\ ]*)'
	while [[ $subject =~ $pattern ]]; do
            echo "${BASH_REMATCH[0]}"
            echo "  key:${BASH_REMATCH[1]}"
            echo "  value:${BASH_REMATCH[2]}"
	    subject=${subject/${BASH_REMATCH[0]}/""}
	done
    done }


このスクリプトは、「カレントディレクトリ以下の xxxx.ts ファイルを探して(find)、『@key=value』という形式のフォルダ名をパタンマッチで解析して、キー名と値を取得する」というものです。
まず、findによりパスが与えられます。

  ./@scale=720x406/@encoder=bontsdemux/@sound=0/recorded.ts

これを、パタン*2でマッチングさせ、

[[ $subject =~ $pattern ]]

一致部分を削除という流れです。

${subject/${BASH_REMATCH[0]}/""}

次が実行例。最初の行が、record.tsのパスを表示させている部分(echo "$f")です。

$ depconv.sh
./@scale=720x406/@encoder=bontsdemux/@sound=0/recorded.ts
@scale=720x406
  key:scale
  value:720x406
@encoder=bontsdemux
  key:encoder
  value:bontsdemux
@sound=0
  key:sound
  value:0

補足

  • 上記スクリプトは、ファイル名が「@scale=720x406 @sound=1 ニュース.ts」となっていたら解析してしまいます。「$(dirname "$f")」とかで削るとか、ありです。
  • patternの行はループの外に出しても良かったかな?
  • 重複「./@scale=720x406 @encode=mencode/@scale=1280x720/recorded.ts」があってもキー・値ペアが取得できるようにするためにループが必要なのであって、先勝ちにするなら、次のように書けます。

find . -type f -path "*.ts" | {
    while read f
    do
	echo "$f"
        [[ $f =~ @scale=?([^\/\ ]*) ]] && echo ()
    done }

*1:とは言え、gオプションが使えても、グループ->キャッチできるとは限らない

*2: '@([a-zA-Z]+)=?([^\/\ ]*)'...@で始まる[a-zA-Z]英字の+並びを()グループして、=は?あってもなくても、つぎに/か空白^以外が*続くならば、これを()グループ