稳健地构建路径


16

假设我在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数组中有多少个)。

Answers:


12

您可以使用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:“为了满足参数,将根据需要重复使用格式字符串。”


单一%方法适用于问题中提到的单个尾部斜杠。为了满足多个斜杠的需要,${parts[@]%%/*}可以使用。这里是指向更多有关斜杠问题的信息的链接:双重斜杠在UNIX路径中意味着什么?'cd dir / subdir //有效吗?
Peter.O 2011年

2
@fered:/*在这种情况下,并不意味着零个或多个斜杠,而是一个斜杠,后跟任意数量的字符。这意味着,如果您的路径以斜杠开头,则结果将为空字符串!
2011年

按照示例,我曾考虑过只有斜杠。然而,为了适应斜线的可能性(ES),bash的extglob(与正则表达式)可以通过使用.. shopt -s extglob; ${parts[@]%%/+(/)}...
Peter.O

15

简单的答案是停止担心并喜欢多个斜线。多个斜杠与单个斜杠具有相同的效果(除了//在几个系统上以开头的路径具有不同的含义;我只能命名Windows上的Unix仿真层)。那是设计使然,能够组合文件名而不必担心多个斜杠是该设计决定的主要部分。

要连接数组元素,在zsh中,您可以使用j 参数扩展标志

dir=${(j:/:)FOLDERS}

您可以在使用时压缩重复的斜杠,但这纯粹是装饰性的。

setopt extended_glob
dir=${${(j:/:)FOLDERS}//\/\/##/\/}

在ksh和bash中,可以使用的第一个字符$IFS作为分隔符来连接数组。然后,您可以压缩重复的斜杠。在bash中,您需要执行shopt -s extglob以下代码段的最后一行中的ksh glob。

IFS=/
dir="${FOLDERS[*]}"
unset IFS
dir=${dir//\/+(\/)//}

3

怎么sed不为您工作?sed 's|/\+|/|g'串联后或sed 's|/||g'之前尝试。


1

bash 4引入了扩展的globing,可在参数替换中启用正则表达式匹配${var....}...默认情况下处于关闭状态。要为您的脚本启用它,只需设置shell选项extglob ...

假设$ dir ==/home/me/////////stuff//items

shopt -s extglob; dir="${dir//+(\/)//}"

$ dir的结果值

/home/me/stuff/items  

这是一些做与不做的例子-Bash Extended Globbing

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.