我有一个用文件名和路径填充的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}
也不起作用。
这可能是我工程过度工程的一个主要例子,但如果有办法做到这一点并且我还没想到它就会很好。
答案 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}"
其中
在bash中更简单地应用这种字符串操作将是:
$ TEST="1234567890"
$ echo ${TEST:3}
4567890
$ echo ${TEST:3:4}
4567