簡體   English   中英

為什么Shell腳本中的引號與Shell命令中的引號行為不同?

[英]Why do quotes in shell scripts behave differently from quotes in shell commands?

我在Windows 10和bash上使用WSL(Ubuntu 18.04)。

我有一個文件filename.gpg內容:

export SOME_ENV_VAR='123'

現在,我運行以下命令:

$ $(gpg -d filename.gpg)
$ echo $SOME_ENV_VAR
'123' <-- with quotes

但是,如果我直接在外殼中運行它:

$ export SOME_ENV_VAR='123'
$ echo $SOME_ENV_VAR
123 < -- without quotes

為什么會這樣呢? 為什么使用$()運行命令與直接運行命令有區別?

另外:我使用eval $(gpg -d filename)使它工作,我不知道為什么會這樣。

Shell腳本中的引號與Shell命令中的引號沒有什么不同。

使用$(gpg -d filename.gpg)語法,您不是在執行Shell腳本,而是執行常規的單個命令。

您的命令做什么

  1. 它執行gpg -d filename.gpg
  2. 根據結果​​,它以第一個(IFS分隔)字作為命令執行
  3. 這需要每隔一個 (IFS分隔)的話,包括從附加線路的話,作為其參數
  4. 執行命令

從以下實際示例中,您可以看到它與執行Shell腳本有何不同:

  1. 從filename.gpg中刪除導出一詞:該命令為SOME_ENV_VAR='123' ,這不能理解為變量賦值(您將獲得SOME_ENV_VAR='123': command not found )。
  2. 如果添加多行,它們將不會被理解為單獨的命令行,而是被視為第一個命令( export )的參數。
  3. 如果將export SOME_ENV_VAR='123'更改為export SOME_ENV_VAR=$PWD ,則SOME_ENV_VAR將不包含變量PWD的內容,而是字符串$var

為什么會這樣呢?

查看分析命令時bash如何執行擴展

有很多步驟。 $(...)被稱為“命令替換”,是第四步。 完成后,將不再執行之前的任何步驟。 這就解釋了為什么刪除export字時命令不起作用,以及為什么變量未替換結果。

此外,“引用刪除”是最后一步, 手冊內容如下

刪除了由於上述擴展之一而導致的所有未加引號的字符'\\','''和'“'

由於單引號是由“命令替換”擴展產生的,因此不會將其刪除。 這就是SOME_ENV_VAR的內容為'123'而不是123

為什么eval有效?

因為eval會觸發另一個完整的參數解析。 整個擴展集將再次運行。

從手冊

將參數串聯在一起成為單個命令,然后讀取並執行

請注意,這意味着您仍在運行一個命令,而不是Shell腳本。 如果filename.gpg腳本有幾行,則隨后的行將添加到第一個(也是唯一的)命令的參數列表中。

那我該怎么辦?

只需使用source流程替換即可

source <(gpg -d filename.gpg)

eval相反, source用於在當前上下文中執行shell腳本。 進程替換提供了一個偽文件名,其中包含替換結果(即gpg的輸出)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM