是否可以在一次操作中应用两个匹配的模式转换?

VxJ*_*nxV 7 bash shell

我有一个填充了文件名和路径的bash变量:

SONG="~/Music/Mine/Cool Title Bro.flac"
Run Code Online (Sandbox Code Playgroud)

在我尝试使标记变得更加容易的过程中,我对变量应用了一些转换以隔离标题:

echo "${SONG#\~/Music/Mine/}" # which prints: Cool Title Bro.flac
Run Code Online (Sandbox Code Playgroud)

我知道也可以删除后缀${SONG%%.flac}.

但是,是否可以在单个操作中删除前缀和后缀?

这个:

${SONG#\~/Music/Mine/%%.flac}
Run Code Online (Sandbox Code Playgroud)

大概是因为它试图将文字%%.flac作为前缀的一部分进行匹配.反过来不起作用(%%.flac#~/[...]),我甚至疯了似试

${${SONG#~/Music/Mine/}%%.flac}
Run Code Online (Sandbox Code Playgroud)

这也行不通.

这可能是我工程过度工程的一个主要例子,但是如果有办法做到这一点并且我还没有弄清楚它会很好.

jed*_*rds 3

echo "1:"
if [[ "$SONG" =~ \~/Music/Mine/(.*)\.flac ]] ; then SONG=${BASH_REMATCH[1]} ; fi
echo $SONG

echo "2:"
[[ "$SONG" =~ \~/Music/Mine/(.*)\.flac ]] && SONG=${BASH_REMATCH[1]}
echo $SONG
Run Code Online (Sandbox Code Playgroud)

1 和 2 使用 bash 正则表达式。第一个示例具有额外的优点,else如果您的字符串与预期的格式不匹配,则能够中断分支。*第二个示例更干净一些。在这两种情况下,如果与${SONG}模式不匹配,则保持不变。

但使用 awk 或 sed 可能更容易理解。例如:

echo "3:"
SONG=$(echo "$SONG" | sed -r 's:~/Music/Mine/(.*)\.flac:\1:')
echo $SONG
Run Code Online (Sandbox Code Playgroud)

[*]请参阅下面 DennisWilliamson 关于使用||获取else分支的注释。

  • +1 您可以通过添加“||”对第二个版本执行“else” foo` 最后。尽管OP想要单个操作,但通常最好将正则表达式放在变量中。另外,应该对点进行转义,使其成为字面的“\.flac”。“SONG”周围的花括号在这里是多余的。展开变量时始终引用变量:`echo "$SONG"。 (2认同)