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)
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)