$ echo > 1 2 3; ls -latr 1; cat 1
-rw-rw-r-- 1 kahn kahn 4 Jun 23 14:05 1
2 3
这与重定向的评估有关吗>
?这样:
echo > 1 2 3
技术上也可以重写为:
echo 2 3 > 1
?
是否有任何资源可以帮助您更好地了解 IO 重定向的操作顺序及其评估方式?我承认这个例子可能不是有用的,甚至不是经常发生的,但我想更好地理解这里到底发生了什么。
答案1
您可以参考的合适资源是 POSIXshell语法,它将一个简单的命令定义为:
simple_command : cmd_prefix cmd_word cmd_suffix | cmd_prefix cmd_word | cmd_prefix | cmd_name cmd_suffix | cmd_name ;
这里最相关的部分是 的定义command_suffix
:
cmd_suffix : io_redirect | cmd_suffix io_redirect | WORD | cmd_suffix WORD ;
这是递归的,允许重定向和命令参数以任何顺序出现。
此外,POSIX 定义了重定向语法作为
[n]redir-op word
n
虽然可选数字和重定向运算符之间不允许有空格(>
在您的情况下),但重定向运算符和后面的单词之间允许有任意数量的空格。扩展后,word
( 1
,在您的情况下) 用作流定向到(或来自)的文件的名称。
因此,写同样合法
$ echo > 1 foo bar
# ^^^^ ^^^^^^^^^^^^^
# \ \
# \ cmd_suffix
# \ ^^^ ^^^ ^^^
# \ \ \ \
# \ \ \ WORD
# \ \ WORD
# \ io_redirect
# cmd_name
或者
$ echo foo >1 bar
甚至
$ echo > 1 foo > 1 bar > 1
(当然,重复> 1
没有任何意义)。
为了完整起见:cmd_prefix
的定义中的thesimple_command
本身是递归定义的:
cmd_prefix : io_redirect | cmd_prefix io_redirect | ASSIGNMENT_WORD | cmd_prefix ASSIGNMENT_WORD ;
这意味着重定向和变量赋值可以以任何顺序出现在命令之前。
例如,您可能会:
$ LC_ALL=C <infile sort >outfile 2>errfile
# ^^^^^^^^^^^^^^^^ ^^^^ ^^^^^^^^^^^^^^^^^^
# \ \ \
# cmd_prefix cmd_word cmd_suffix
或者
$ 2>errfile >outfile <infile LC_ALL=C sort
或者
$ LC_ALL=C sort <infile 2>errfile >outfile
这些都是同样合法的,但必须记住,重定向和变量赋值以及扩展是从左到右执行的,并且它们的顺序可能是相关的(例如,如果infile
不存在,则outfile
不会被截断cat <infile >outfile
)是在cat >outfile <infile
)。
答案2
单词在空格上分开。带引号的字符串将被视为单个单词,无论空格如何。变量的值在使用时是分词的候选者(这就是为什么通常最好用双引号引起来的变量名称,"$var"
)。
重定向运算符使用以下单个单词。
完整的详细信息可以在您的 shell 的手册页中看到(例如man bash
在“扩展”下)
扩展的顺序是:大括号扩展、波形符扩展、参数、变量和算术扩展以及命令替换(以从左到右的方式完成)、分词和路径名扩展。