假设我在 shell 脚本中有几个变量(例如在 zsh 中):
FOLDER_1, FOLDER_2, etc.
这些变量引用从/
.例如,如果我有一条路径/home/me/stuff/items
变量将是:
FOLDER_1='home'
FOLDER_2='me'
FOLDER_3='stuff'
现在,假设我想通过连接变量来重新构建相应的路径。一种可能的方法是按如下方式构建路径:
PATH=$FOLDER_1/$FOLDER_2/$FOLDER_3/
但是,假设某些变量FOLDER_i
带有尾部正斜杠,而其他变量则没有(而且我们不知道是哪些),例如
FOLDER_1='home'
FOLDER_2='stuff/'
FOLDER_3='items'
我的问题是:如何才能稳健地构建路径?(例如,避免双斜杠,并将它们添加到需要的位置)。
我认为做到这一点的一种方法是/
在变量对之间添加always,然后使用删除任何重复项sed
,但我无法使其工作(我不确定我是否/
正确处理sed
)。
还,我是在重新发明轮子吗? (即是否有任何内置功能可以做到这一点?)。
最后,如果变量位于大批,例如FOLDERS
,是否可以在不循环的情况下执行此操作? (或者,通过循环但不知道FOLDERS
数组中有多少个)。
答案1
简单的答案是停止担心并喜欢多重斜线。多个斜杠与单个斜杠具有相同的效果(除了以 开头的路径//
在一些系统上具有不同的含义;Windows 上的 unix 模拟层是我唯一能命名的层)。这是设计使然,能够组合文件名而不必担心多个斜杠是该设计决策的主要部分。
要连接数组元素,在 zsh 中,您可以使用j
参数扩展标志。
dir=${(j:/:)FOLDERS}
您可以在执行此操作时压扁重复的斜杠,但这纯粹是装饰性的。
setopt extended_glob
dir=${${(j:/:)FOLDERS}//\/\/##/\/}
$IFS
在 ksh 和 bash 中,您可以使用第一个字符作为分隔符来连接数组。然后您可以压扁重复的斜杠。在 bash 中,您需要shopt -s extglob
在下面代码片段的最后一行中启用 ksh 全局变量。
IFS=/
dir="${FOLDERS[*]}"
unset IFS
dir=${dir//\/+(\/)//}
答案2
您可以printf
与数组一起使用:
parts=("$FOLDER_1" "$FOLDER_2" "$FOLDER_3");
printf '/%s' "${parts[@]%/}"
# Use "printf -v path" to save it into a variable called "path" instead of printing it
运算%
符修剪尾随字符串,在本例中为/
。通过将其应用于parts[@]
,它会分别修剪每个数组成员。
理解这个技巧的关键printf
在于man 1 printf
:“格式字符串根据需要经常重用以满足参数。”
答案3
怎么sed
不适合你呢?sed 's|/\+|/|g'
在连接之后或之前尝试sed 's|/||g'
。
答案4
bash 4
引入了扩展通配符,它可以在参数替换中启用正则表达式匹配${var....}
...默认情况下关闭。要为您的脚本启用它,只需设置 shell 选项外部全局变量...
假如说$目录==/home/me/////////stuff//items
shopt -s extglob; dir="${dir//+(\/)//}"
结果值$目录
/home/me/stuff/items
以下是一些有关“做”和“不做”的示例——Bash 扩展通配符