如何在 bash 中使用多字符分隔符进行数组扩展?

Wil*_*ard 3 bash shell-script echo printf

我将问题简化为(我相信)最简单的情况。假设我有一个myscript.sh包含以下内容的脚本:

#!/bin/bash
IFS='%20'
echo "$*"
Run Code Online (Sandbox Code Playgroud)

如果我按如下方式运行命令,输出将如下所示:

me@myhost ~ $ ./myscript.sh fee fi fo fum
fee%fi%fo%fum
Run Code Online (Sandbox Code Playgroud)

这是预期的行为,如bash手册页中所述:

   *      Expands  to  the positional parameters, starting from one.  When
          the expansion occurs within double quotes, it expands to a  sin-
          gle word with the value of each parameter separated by the first
          character of the IFS special variable.  That is, "$*" is equiva-
          lent to "$1c$2c...", where c is the first character of the value
          of the IFS variable.  If IFS is unset, the parameters are  sepa-
          rated  by  spaces.   If  IFS  is null, the parameters are joined
          without intervening separators. 
Run Code Online (Sandbox Code Playgroud)

但是,我想得到的是输出:

fee%20fi%20fo%20fum
Run Code Online (Sandbox Code Playgroud)

因此使用多字符分隔符字段而不是单个字符。

有没有办法做到这一点bash


更新:

基于下面来自 mikeserv 的数据,以及为什么 printf 比 echo 好?,我最终做了以下(再次简化为最简单的情况,如上例所示):

#!/bin/bash
word="$1"
shift
if [ "$#" -gt 0 ] ; then
    word="$word$(printf '%%20%s' "$@")"
fi
printf '%s\n' "$word"
unset word
Run Code Online (Sandbox Code Playgroud)

mik*_*erv 5

printf将其格式字符串应用于输出时跟在它后面的每个参数。它是一个bash内置的 shell,可用于将分隔符字符串应用于参数列表 - 有点。

例如:

printf %s:delimit: arg1 arg2 arg3
Run Code Online (Sandbox Code Playgroud)
arg1:delimit:arg2:delimit:arg3:delimit:
Run Code Online (Sandbox Code Playgroud)

问题是,printf不会停止在其参数末尾应用其格式字符串,因此最后一个附加分隔符。这可以在某些情况下处理:

printf %b:delimit: \\0150 \\0145 \\0171\\c
Run Code Online (Sandbox Code Playgroud)
h:delimit:e:delimit:y
Run Code Online (Sandbox Code Playgroud)

printf将 C 和八进制转义解释为%b具有某种格式的 ytes,以及%b\c在某个点输出的格式,这就是为什么printf不在上面的 y后面跟一个:delimit:字符串,因为它的格式字符串否则会指示。

因此,如果您希望从字面上解释每个参数并且没有尾随分隔符,那么您必须在参数列表本身内解决问题:

set -- arg1 arg2 arg3
for arg do shift
    set -- "$@" :delimit: "$arg"
done; shift
printf %s "$@"
Run Code Online (Sandbox Code Playgroud)
arg1:delimit:arg2:delimit:arg3
Run Code Online (Sandbox Code Playgroud)