7

我有一个填充了文件名和路径的 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}

这也不起作用。

这可能是我过度设计的一个典型例子,但如果有办法做到这一点,那就太好了,我只是还没有弄清楚。

4

5 回答 5

3

在某些情况下,bash的扩展模式足够灵活,可以完成您想要的。首先,您必须打开它们:

shopt -s extglob

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

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

扩展模式@(*\/|.*)匹配/ 之前的所有内容(必须对其进行转义,以避免将其与部分参数替换语法混淆),或者匹配句点及其后面的所有内容。//表示每次出现的模式都应该被替换。

于 2012-06-20T12:31:18.517 回答
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分支的说明。

于 2012-06-20T08:30:09.803 回答
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}"

您还可以在支持它的外壳中使用正则表达式分组。jedwards 答案中的示例

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

song='~/Music/Mine/Cool Title Bro.flac'; echo "${song/'~/Music/Mine/'+(*).flac/\1}"
于 2012-06-20T08:29:26.477 回答
0

希望我没有误解你的问题。你想隔离“酷标题兄弟”吗?如果是这样,那么

$ 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

使用任何文件扩展名。

于 2012-06-21T08:52:33.217 回答
-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
于 2012-06-20T08:49:01.070 回答