重定向bas​​h for loop的输出

Mat*_*ley 48 linux bash shell

我有一个简单的BASH命令,看起来像

for i in `seq 2`; do echo $i; done; > out.dat
Run Code Online (Sandbox Code Playgroud)

当这运行输出时seq 2输出到终端并且没有输出到数据文件(out.dat)

我希望标准输出被重定向到out.dat,就像它只是运行命令一样 seq 2 > out.dat

kon*_*box 78

删除你的分号.

for i in `seq 2`; do echo "$i"; done > out.dat
Run Code Online (Sandbox Code Playgroud)

几点建议

同样如Fredrik Pihl所建议的那样,尽量不要在不需要时使用外部二进制文件,或者至少在实际上不使用外部二进制文件时:

for i in {1..2}; do echo "$i"; done > out.dat
for ((i = 1; i <= 2; ++i )); do echo "$i"; done > out.dat
for i in 1 2; do echo "$i"; done > out.dat
Run Code Online (Sandbox Code Playgroud)

另外,请注意words可能导致路径名扩展的输出.

for A in $(echo '*'); do echo "$A"; done
Run Code Online (Sandbox Code Playgroud)

会显示您的文件而不是文字*.

$()在bash和POSIX shell中,还建议使用比backticks(`)更清晰的命令替换语法,并且它支持嵌套.

更清洁的解决方案以及读取变量的输出

while read VAR; do
    ...   
done < <(do something)
Run Code Online (Sandbox Code Playgroud)

read ... < <(do something)  ## Could be done on a loop or with readarray.

for A in "${ARRAY[@]}"; do
    :
done
Run Code Online (Sandbox Code Playgroud)

对于预期的功能,使用printf也可以是更容易的替代方案:

printf '%s\n' {1..2} > out.dat
Run Code Online (Sandbox Code Playgroud)

  • 这个例子让我意识到我可以将`done`语句传递给其他东西,例如`sort`,例如`for f in foo bar baz; 回声$ i | BASE64; 完成| 排序| base64 -d` (3认同)

tob*_*s_k 7

另一种可能性,为了完整起见:您可以在循环内移动输出,使用>>附加到文件(如果存在).

for i in `seq 2`; do echo $i >> out.dat; done;
Run Code Online (Sandbox Code Playgroud)

哪一个更好肯定取决于用例.一次写入文件肯定比附加一千次更好.此外,如果循环包含多个echo语句,所有语句都将转到文件中,那么done > out.dat操作可能更易读,也更容易维护.当然,这种解决方案的优点是它提供了更大的灵活性.

  • 在循环外执行单个重定向肯定更适合性能. (4认同)

sva*_*nte 5

尝试:

(for i in `seq 2`; do echo $i; done;) > out.dat
Run Code Online (Sandbox Code Playgroud)

  • 没有必要将它放在子壳上.必须删除分号才能使块的重定向部分成为可能. (3认同)
  • `for`循环已经是一个复合命令,它将它的主体分组; 这里的子壳是没有意义的. (3认同)
  • 没错,在这种情况下只需删除分号即可.Subshel​​l,(),可用于收集大量命令的输出,比如多个for循环. (2认同)
  • @svante我同意将它包含在内以获得更多命令,但是当你没有必要为子shell创建另一个进程并保持变量从更高的块更改时,你也可以使用`{}`.只有当它无法帮助时,才会将它们放置在管道上,因为它们默认放在子shell上,而不是设置laspipe并且命令在最后,尽管使用流程替换是可行的方法.它. (2认同)