我有以下 bash 脚本,它在同一行输出两个随机数。
#!/bin/bash
for i in 1 2; do
unset var
until [ "$var" -lt 10000 ] 2>/dev/null; do
var="$RANDOM"
done
printf "%s," "${var/%,/}"
done
输出是:
5751,2129,
我试图摆脱我尝试过的逗号,$var
以便"${var/%,/}"
$var = 5751,2129 的输出可以使用。有人能帮忙吗?
像这样分配后:
var="$RANDOM"
,var
变量包含一个来自扩展的字符串$RANDOM
。在 Bash$RANDOM
中,从 到 范围内扩展为十进制0
数32767
。那里没有,
字符,因此尝试,
从以后的扩展中删除是没有意义的$var
。您在输出中观察到的逗号字符来自这部分代码:
在循环的每次迭代中都会调用此命令,因此每次迭代都会在输出中添加一个逗号字符。
已打印的内容不能不打印。有细微差别:
the_script | the_filter
);或者您可以将脚本某些部分的输出通过管道传输到脚本内的过滤器。在后一种情况下,整个脚本的输出将被过滤;脚本部分已经打印的内容仍然不是未打印的;我的意思是它确实进入了过滤器。过滤器稍后将其删除。摆脱不需要的逗号的正确方法是首先不要打印它;或在脚本中过滤它。有几种方法可以做到这一点,我不打算找到所有方法。我将讨论其中的一些。我假设您想知道对于具有两次以上迭代的循环的可能方法;可能是预先不知道迭代次数的循环;也许 for 循环不是由数字枚举的;也许 for 可能永远不会完成的循环(例如
while true
,而不是for
)。注意:您使用
printf "%s," "${var/%,/}"
了 ,它不打印尾随换行符。如果可能的话,我会尝试复制这种行为。几种可能的方法:
循环的内部不依赖于
$i
. 您可以摆脱循环并使用两个单独的变量:笔记:
for i in {1..100}
呢?)您可以将当前代码放在管道中并过滤掉尾随的逗号。例子:
笔记:
sed
(或您使用的任何过滤器)可能会或可能不会处理循环产生的不完整行(未由换行符终止的行)。在这种情况下sed
,取决于实施。sed
确实处理了它,它仍然可以用换行符终止其输出。sed
(或您使用的任何过滤器)可能无法处理太长的行。上面的特定代码生成了一条相当短的线,但通常(想象许多迭代)长度可能是一个问题。sed
,作为面向行的工具,必须在处理之前读取整行。在这种情况下,它必须读取其整个输入。在所有迭代完成之前,您不会从中得到任何东西。您可以将当前代码的输出捕获到变量中。最后,在扩展变量时删除尾随逗号:
笔记:
printf
(循环外)之前是静默的。在所有迭代完成之前,您将一无所获。printf
是内置的,它可能printf "%s" "${capture%,}"
可以在不达到命令行长度限制的情况下处理。我没有对此进行彻底测试,因为 IMO 将大量数据存储在 shell 变量中并不是最佳实践。如果您知道输出的长度有限,那么这种做法仍然是合理的。(记录一下:上面的代码肯定会产生非常短的输出。)$()
删除所有尾随换行符。这意味着您不能使用变量来存储任意输出并在以后准确地重现它。(记录一下:在上面的代码中,内部的片段$()
不会生成 NUL 或尾随换行符。)您可以将每次迭代附加到某个变量,而不是捕获输出:
笔记:
capture+="$var,"
. (注意:如果为变量设置了整数属性,则=+
表示“添加”,而不是“追加”。)您可以检测最后一次迭代并使用没有的格式
,
:笔记:
for i in "${arr[@]}"
),那就更难了。您可以检测第一次迭代并使用不带
,
. 请注意,您可以在原始代码中使用,%s
而不是;%s,
那么你会得到,5751,2129
而不是5751,2129,
. 通过此更改,上述任何避免或删除尾随逗号的方法都可以转换为避免或删除前导逗号的方法。最后一种方法变成:笔记:
1
(或一般固定的唯一字符串)开始,则检测第一次迭代很容易。for i in "${arr[@]}"
. 您不应该检查if [ "$i" = "${arr[1]}" ]
,因为数组中可能有一个与"${arr[1]}"
后面相同的元素。解决这个问题的一种直接方法是为循环保留一个索引(index=1
在循环之前,然后在每次迭代结束时加一)并针对1
;测试它的值。我会发现这样的代码有点麻烦。你可以让
,
自己来自一个变量。输入变量为空的循环,并,
在每次迭代结束时将其设置为。这将在第一次迭代结束时有效地改变一次值。例子:笔记:
我个人觉得这种方法很优雅。
一般注意事项:
sed
或另一个过滤器的可能例外)。如果您需要整个输出形成正确终止的文本行,请在循环之后运行printf '\n'
(或唯一)。echo
,
成为分隔符,而不是终结者。$var
这意味着如果在迭代中扩展为空字符串,则具有恰好零次迭代的循环将生成与具有恰好一次迭代的循环相同的空输出。在我们的例子$var
中,每次都扩展为一个非空字符串,并且我们知道我们有不止零次迭代;但在一般情况下,使用分隔符而不是终止符可能会导致歧义。