在 Bash 中提取子字符串的更好方法

在 Bash 中提取子字符串的更好方法

我有一个名为的文件列表mp3,如下所示:

$artist/$album ($year)/$tracknum $title.mp3

其中许多曲目的标签不正确或缺失,我正在通过使用id3v2和正则表达式,因为文件名都是正确的。下面是我设置标题的示例:

for mp3 in *.mp3; do id3v2 -t "$(echo $mp3 | cut -d. -f1 | cut -d\  -f2-)" "$mp3"; done

(注意:之所以使用引号是因为标题中经常有空格,如果不使用空格,则会导致 bash 发出警告)

我的问题是:有没有更好的方法从这些文件中提取特定的子字符串?就标题而言,如果grep -o不匹配,我就无法使用$tracknum,因为许多曲目的标题中都有数字和空格(这意味着我需要"([0-9a-zA-Z ]+)"我的模式,它匹配之前的整个文件名.mp3)。

我几乎确信有更好的方法可以做到这一点。有吗?

答案1

如果您想要提取标题(并且,如果有用的话,还有曲目编号),您应该可以这样做:

read -r tracknum title <<<$(basename "$mp3" .mp3)

对于其他部分,我将首先拆分文件名以/隔离各个部分。例如:

album_year=$(cut -d/ -f2 <<<"$mp3")
album=${album%\ (*)}
year=${album_year:-5:4}

最后一个取决于实际存在的年份和四位数字的长度;如果不能保证,那么您可以使用更笨拙的表达式来完成:

year=${album_year:$((${#album}+2)):$((${#album_year}-${#album}-3}

此外,如果您不知道该部分在路径中有多深album_year,您可以使用以下命令提取倒数第​​二段(即文件的直接目录):

album_year=$(basename "$(dirname "$mp3")")

或者,你可以将整个路径拆分为一个数组:

IFS=/ read -ra segments <<<"$mp3"
album_year=${segments[-2]}

相关内容