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

时间:2012-06-20 08:11:46

标签: bash shell

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

SONG="~/Music/Mine/Cool Title Bro.flac"

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

echo "${SONG#\~/Music/Mine/}" # which prints: Cool Title Bro.flac

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

但是可以在一次操作中删除前缀和后缀吗?

此:

${SONG#\~/Music/Mine/%%.flac}

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

${${SONG#~/Music/Mine/}%%.flac}

也不起作用。

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

5 个答案:

答案 0 :(得分: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

1和2使用bash正则表达式。如果您的字符串与预期的格式不匹配,第一个示例还具有能够进入else分支的附加优势。*第二个示例更清晰。在这两种情况下,如果${SONG}与模式不匹配,则保持不变。

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

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

[*] 请参阅DennisWilliamson关于使用||获取else分支的说明。

答案 1 :(得分:2)

不,不可能。使用两个操作。

tmp="${SONG#\~/Music/Mine/}"; echo "${tmp%.flac}"

好吧,如果你疯了的话,这是可能的。

a="~/Music/Mine/Cool Title Bro.flac"
echo "${a:b=$(b=${a%${a#\~/Music/Mine/}};echo ${#b}):$(c=${a%.flac};echo ${#c})-b}"

您也可以在支持它的shell中使用正则表达式分组。 jedwards answer

中的示例

也可以使用ksh93模式分组来完成。

song='~/Music/Mine/Cool Title Bro.flac'; echo "${song/'~/Music/Mine/'+(*).flac/\1}"

答案 2 :(得分:2)

在某些情况下,bash的扩展模式足够灵活,可以实现您的目标。首先,你必须打开它们:

shopt -s extglob

然后,您可以使用参数扩展指定应删除的模式列表:

echo ${SONG//@(*\/|.*)}

扩展模式@(*\/|.*)匹配 所有内容一直到/(必须进行转义,以避免将其与参数替换语法的一部分混淆),一段时间,一切都跟着它。 //表示应该替换每个模式的出现。

答案 3 :(得分:0)

希望我没有误解你的问题。你想隔离“Cool Title Bro”? 如果是,那么

$ echo "~/Music/Mine/Cool Title Bro.flac"
~/Music/Mine/Cool Title Bro.flac
$ echo "~/Music/Mine/Cool Title Bro.flac"|sed 's/.*\/\(.*\).flac/\1/'
Cool Title Bro

没有一点正则表达式无法管理。 或者

$ echo "~/Music/Mine/Cool Title Bro.flac"|sed 's/.*\/\(.*\)\..*/\1/'
Cool Title Bro

使用任何文件扩展名。

答案 4 :(得分:-1)

如果我只能在一行中完成,而且我不关心易读性,我将使用

echo "${SONG:13:${#SONG} - 18}"

其中

  • 13是字符串“〜/ Music / Mine /”
  • 的长度
  • 18是字符串“〜/ Music / Mine /”的长度加上“.flac”的长度

在bash中更简单地应用这种字符串操作将是:

$ TEST="1234567890"
$ echo ${TEST:3}
4567890
$ echo ${TEST:3:4}
4567
相关问题