提供对复合命令中使用的命令的重定向

提供对复合命令中使用的命令的重定向

如果我想为命令、、和中的输入或输出( < myfile、 或> myfile)提供重定向test-commandsconsequent-commandscommand1command2

if test-commands; then
consequent-commands;

until test-commands; do consequent-commands; done

while test-commands; do consequent-commands; done

command1 && command2

command1 || command2

我应该在哪里放置重定向?

例如,我看到

while read a; 
  do echo "$a"; 
done < myfile;

我想知道为什么放在< myfile后面done,而不是后面read a

这也让我思考得更广泛(作为本文的开头部分):

  • 复合命令中出现的命令应置于何处?

  • 重定向是输出还是输入有关系吗?

  • 如果我将重定向放在复合命令的末尾,我如何知道重定向适用于复合命令中的哪个组件命令?

谢谢。

答案1

您可以将重定向放置在简单命令中的任何位置(即调用别名、函数、内置函数或带参数的可执行文件)。另一方面,如果您想对复合命令应用重定向,则必须在之后进行重定向。这就是 shell 语法的设计方式。例如,以下内容是等效的:

<myinput mycommand argument
mycommand <myinput argument
mycommand argument <myinput

而重定向不能移入

while …; do …; done <myinput
{ command1; command2; } <myinput

仅当复合命令以关键字或标点符号结尾时,您才能应用重定向。要将重定向应用于foo && baror foo; baror之类的内容foo | bar,请将命令放在大括号中,例如

{ foo && bar; } <myinput

脚本

while read a; do
  echo "$a"
done <myfile

while read a <myfile; do
  echo "$a"
done

两者在语法上都是正确的,但第二个没有做任何有用的事情。命令上的重定向运算符意味着:

  1. 打开指定的文件。
  2. 将指定的文件附加到必需的文件描述符(例如 0 表示<)。
  3. 运行命令。
  4. 关闭文件描述符。

因此,read a <myfile每次迭代时都会再次打开文件,这意味着它会永远读取第一行。

如果要使用 while-read 循环并希望保留循环体的周围标准输入,请从不同的文件描述符读取。

while read a <&3; do
  # commands that can use stdin
done 3<myfile

重定向运算符<&3仅执行文件描述符复制,它不会“再次打开文件”——在上面的枚举中,没有步骤 1。

答案2

对于简单的命令,重定向定位是灵活的,只要它位于同一行并且在任何;.这些都是有效的:

command1 arg <file
<file command1 arg
command1 <file arg

从风格上来说,您会发现第一种形式通常是首选。

对于通过管道或条件连接的命令,重定向显然应该与关联命令位于同一侧。如果第一个命令必须接收输入,那么您需要:

command1 <file || command2

对于 command2 接收输入:

command1 || command2 <file

while在,和其他块复合命令的情况下,for将重定向放在末尾的必要性只是语法上的现实。

<file { command1 || command2; } # error
{ command1 || command2; } <file  # okay

例如,复合命令在此上下文中充当单个命令,因此重定向输入不能以 command2 为目标并排除 command1。

当然,管道有时也是一种选择,因此上面的第二个示例类似于:

cat file | { command1 || command2; }

在 while 循环的情况下:

cat myfile | while read a; do ...

我在所有这些示例中都使用了输入,但同样适用于输出。需要注意的是,如果同时使用输入和输出或其他多重重定向配置。重定向是从左到右处理的。

这里还有一些阅读内容:

http://wiki.bash-hackers.org/syntax/redirection

http://wiki.bash-hackers.org/howto/redirection_tutorial

相关内容