如何在 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
以上)。
这行得通,但语法很丑陋。有没有更简洁的方法来做到这一点(同样,同时保持可移植性)?也许是干净的 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 命令周围加上 set -f
和 set +f
以禁用和启用 glob 扩展。
单行sed是
prefixed_dirs=$(echo "$mydirs" | sed -E "s, , $root/,g; s,^,$root/,; s,//,/,g")
使用 $(...)
而不是 `...`
-- 请参阅
https://github.com/koalaman/shellcheck/wiki/SC2006
了解更多详情。
我有一个以 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
以上)。
这行得通,但语法很丑陋。有没有更简洁的方法来做到这一点(同样,同时保持可移植性)?也许是干净的 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 命令周围加上 set -f
和 set +f
以禁用和启用 glob 扩展。
单行sed是
prefixed_dirs=$(echo "$mydirs" | sed -E "s, , $root/,g; s,^,$root/,; s,//,/,g")
使用 $(...)
而不是 `...`
-- 请参阅
https://github.com/koalaman/shellcheck/wiki/SC2006
了解更多详情。