我有一个由空格分隔的文件字符串,这些文件可能以"为前缀,也可能不以"作为前缀/"(即,它们的路径相对于给定的根(:
mydirs='a /b/c /d/e/f g /h/i'
我需要用用户提供的根作为每个文件的前缀。我需要一种便携的方式来做到这一点(不用说,我更喜欢速度,所以欢迎内置(。所以我们都在同一页上,通过";便携式;我的意思是";可在不同的linux shell(sh、bash、ksh、zsh、tsh、csh等(之间移植";
目前,我的解决方案是:
root="my_root" # User-supplied root directory
prefixed_dirs=`echo $mydirs |
tr ' ' '
' | sed 's;^/*;prefix/;' | tr '
' ' '`
这也在我的行的末尾加了一个空格,这不是我想要的。
我想要的输出是用前缀为文件的单行回显给我,如下所示:
my_root/a my_root/b/c my_root/d/e/f my_root/g my_root/h/i
我试着在SO中搜索答案,但我并没有真正找到我想要的答案(如果有解决方案,请给我指一个(。我知道sed默认情况下对新行进行操作,所以我本质上是想让sed对子字符串的开头进行操作(我不能只找空格,因为它会跳过上面的a
(。
这是可行的,但语法很难看。有没有一种更干净的方法可以做到这一点(同样,在保持便携性的同时(?也许是一个干净的awk
或perl
一行(同样,必须是便携式的(?一个干净的sed一个衬垫得两分!
非常感谢!
您可以使用set
命令将字符串成分设置为位置参数,然后运行POSIX支持的参数扩展技术来删除前导/
(如果存在(。
请注意,对未引用的变量展开使用set
也要进行glob展开。确保没有发生这种情况的余地。
root="my_root"
mydirs='a /b/c /d/e/f g /h/i'
set -- $mydirs
for arg; do
printf '%s ' "${root}/${arg#/}"
done
或者,如果您预计会进行glob扩展,请使用set -f
和set +f
包围set命令,以禁用并启用glob回扩。
sed单行为
prefixed_dirs=$(echo "$mydirs" | sed -E "s, , $root/,g; s,^,$root/,; s,//,/,g")
使用$(...)
而不是`...`
--请参阅https://github.com/koalaman/shellcheck/wiki/SC2006了解更多详细信息。