为什么 echo > 1 2 3 创建一个名为 1 且内​​容为 2 3 的文件?

为什么 echo > 1 2 3 创建一个名为 1 且内​​容为 2 3 的文件?
$ 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在“扩展”下)

扩展的顺序是:大括号扩展、波形符扩展、参数、变量和算术扩展以及命令替换(以从左到右的方式完成)、分词和路径名扩展。

相关内容