shell zsh basename和${var%.*}

ckocjqey  于 2023-08-07  发布在  Shell
关注(0)|答案(2)|浏览(92)

如何理解file2和file3之间的不同输出?

(base) ➜  Youtube cat 1.sh
base="/VS/Harry Potter - Hedwig's Theme (Harmonica Ver.) [w2kuM-Rp_IY].info.json"
echo "base:  $base";
dir=$(dirname "$base");
filename=$(basename "$base");
file=${${filename%.*}%.*};
file2=${${"$(basename $filename)"%.*}%.*};
file3=${${$(basename $filename)%.*}%.*};
echo "file:  $dir/$file";
echo "file2: $dir/$file2";
echo "file3: $dir/$file3";

(base) ➜  Youtube zsh 1.sh
base:  /VS/Harry Potter - Hedwig's Theme (Harmonica Ver.) [w2kuM-Rp_IY].info.json
file:  /VS/Harry Potter - Hedwig's Theme (Harmonica Ver.) [w2kuM-Rp_IY]
file2: /VS/Harry Potter - Hedwig's Theme (Harmonica Ver.) [w2kuM-Rp_IY]
file3: /VS/Harry Potter - Hedwig's Theme (Harmonica Ver [w2kuM-Rp_IY]

字符串
看起来basename命令返回了一个按空格分割的serval部分,${var%.*}命令对每个部分都有效。

kuhbmx9i

kuhbmx9i1#

看起来basename命令返回了一个按空格分割的serval部分,${var%.*}命令对每个部分都有效。
差不多吧
来自命令替换的文档:
如果替换没有用双引号括起来,则使用IFS参数将输出拆分为单词。
从参数扩展部分开始,讨论模式删除和替换:
...当 name 为数组且替换不带引号时,或者使用(@)标志或name[@]语法时,分别对每个数组元素进行匹配替换
这就是使用不带引号的命令替换时遇到的情况。它的输出被分解成单词,每个单词都被检查是否有匹配的模式要删除。

20jt8wwn

20jt8wwn2#

您没有对$( command substitution )加上引号,因此它被IFS字符分割,并被后续嵌套的${}参数扩展视为数组值。作为数组值,${param%pattern}扩展应用于每个元素。然后,由于file3=...是一个标量赋值,结果由IFS的第一个字符连接。任何命令的输出都会发生这种情况--它并不特定于basename。如果输入字符串包含>1种类型的IFS字符或>1个连续IFS字符,则效果将更加明显。
在zsh中,你可以使用t(tail)或h(head)扩展修饰符,而不是外部的basenamedirname工具。
r(root)修饰符似乎更适合您的用例,即删除“extension”部分:

base="/VS/Harry Potter - Hedwig's Theme (Harmonica Ver.) [w2kuM-Rp_IY].info.json"
file4=$base:r:r
typeset -p file4

字符串
它只会作用于路径的尾部,所以你不需要执行你自己的split->modify->join处理。file4=$base:F[2]r是另一种选择,而不是将:r加倍。即F:expr:修改器重复以下r修改器2次。

相关问题