Io-Redirection

為什麼 echo > 1 2 3 會創建一個名為 1 且內容為 2 3 的文件?

  • July 9, 2020
$ 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 重定向的操作順序以及如何評估它?我承認這個例子可能不是很有用,甚至不會經常發生,但我想更好地了解這裡到底發生了什麼。

您可以參考的適當資源是 POSIX shell 語法,它定義了一個簡單的命令:

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定義中simple_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)。

引用自:https://unix.stackexchange.com/questions/594631