bash(macos)を使用して文字列を含む行の一部を変更する

bash(macos)を使用して文字列を含む行の一部を変更する

音楽プレイリストファイル.m3uで文字列「[LD]」を含む行を識別し、その行を特定の変更で更新する必要があります。

例えば:

/music/Miles Davis/1959 - Kind of Blue [LD]/Miles Davis - So What.mp3

次のようにする必要があります。

/music/_lossless/Miles Davis/1959 - Kind of Blue/Miles Davis - So What.mp3

つまり。 「/music/」に文字列「_lossless/」を挿入すると、音楽ファイルのパスから文字列「[LD]」が削除されます。

各ファイルは他の多くのプロセスも実行する必要があるため、ファイルにforループを使用します。

for f in *.m3u;
    do

    # I can identify the lines using:
    fgrep -n "[LD]" "$f"
    
    # I can grab the line number using:
    ld_line=$(fgrep -c "[LD]" "$f")

    # and have tried processing the changes using sed, but it is not working..
    #sed "$ld_lines![LD]!!" "$f"

    # Ive also tried using sed as follows:
    sed '![LD]!s!music!music/_lossless!' "$f"

    # but neither of the above approaches either work or handle both modifications

  done

ソリューションはsedを使用する必要はありません。何でもベストです。

答え1

sed '/ \[LD\]/ { s///; s,/,/_lossless/,2; }' file

部分文字列を含むファイルの行を見つけるには、 で [LD]正規表現を使用できます。正規表現が持つ特別な意味を失うには、エスケープする必要があります。脱出する必要はありませんが、対称性のために脱出します。/ \[LD\]/sed[]

部分文字列を含む行を見つけると、その文字列を代替 [LD]文字列に置き換えることができます。つまり、削除しますs///。空の正規表現を使用すると、一致する式である最も近い式が再利用されます [LD]

次の置換は、2番目のものを/文字列で置き換えることです/_lossless//末尾にあるものを使用して、その行で正規表現に一致する2番目の項目を選択し、便宜上、スラッシュの代わりに2カンマをコマンド区切り文字として使用します。

ループ内の.newファイル名サフィックスを使用してファイルを作成します。

for name in *.m3u; do
    sed '/ \[LD\]/ { s///; s,/,/_lossless/,2; }' -- "$name" >"$name".new
done

macOSでファイルを変更するにはsed -i '' ...

for name in *.m3u; do
    sed -i '' '/ \[LD\]/ { s///; s,/,/_lossless/,2; }' -- "$name"
done

破壊的なコマンドをテストする前にデータをバックアップすることを忘れないでください。

答え2

あなたはこれを試すことができますsed

for f in *.mp3; do
    var1=$(sed -E 's|(.[^/]*)(.[^[]*).*](.*)|\1/_lossless\2\3|' "$f")
    mv "$f" "var1"
done

出力

/music/_lossless/Miles Davis/1959 - Kind of Blue /Miles Davis - So What.mp3

関連情報