使用 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

IE。字符串“_lossless/”插入到“/music/”之后,字符串“[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]

下一个替换是将第二个替换/为字符串/_lossless/。我们/使用末尾的 来选择该行中正则表达式的第二个匹配项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

相关内容