如何在Shell脚本中为空间分隔字符串中的子字符串添加前缀



我有一个由空格分隔的文件字符串,这些文件可能以"为前缀,也可能不以"作为前缀/"(即,它们的路径相对于给定的根(:

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(。

这是可行的,但语法很难看。有没有一种更干净的方法可以做到这一点(同样,在保持便携性的同时(?也许是一个干净的awkperl一行(同样,必须是便携式的(?一个干净的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 -fset +f包围set命令,以禁用并启用glob回扩。

sed单行为

prefixed_dirs=$(echo "$mydirs" | sed -E "s, , $root/,g; s,^,$root/,; s,//,/,g")

使用$(...)而不是`...`--请参阅https://github.com/koalaman/shellcheck/wiki/SC2006了解更多详细信息。

最新更新