如何在 Shell 脚本中为 Space 定界字符串添加前缀

How to Prefix Substrings in a Space-Delimited String in Shell Script

我有一个以 space 分隔的文件字符串,这些文件可能以或不以“/”为前缀(即它们的路径是相对于给定根目录的):

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 '
' ' '`

它还在我的行尾放了一个 space,这不是我想要的。

我想要的输出是回显给我的单行文件前缀,如下所示:

my_root/a my_root/b/c my_root/d/e/f my_root/g my_root/h/i

我已经尝试在 SO 中搜索答案,但我还没有真正找到我要找的东西(如果有解决方案,请指点我)。我知道 sed 默认情况下在新行上运行,所以我实际上是在尝试让 sed 在子字符串的开头运行(我不能只查找 spaces 因为它会跳过 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 命令周围加上 set -fset +f 以禁用和启用 glob 扩展。

单行sed是

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

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