Bash

為什麼 cat 命令重定向新文件會立即執行?

  • September 6, 2019

我想生成一個可以稍後呼叫的 bash 文件,像這樣

cat <<-SCRIPT >test-$$
       #!/bin/bash
       osType=$(grep -Po '^NAME="\K[^"]*' /etc/os-release)
       if [ "$osType" = ...]
       then
           ...
       fi
       exit
   SCRIPT

當我調試時,grep 命令總是以正確的方式執行,為什麼?也嘗試使用 awk 相同的錯誤

但如果我這樣做

cat <<-SCRIPT >test-$$
       #!/bin/bash
       rpm -q somepackage > test-$$
       rm test-$$-lock
       exit
   SCRIPT

我沒有看到 rpm 命令以正確的方式執行?也做測試——

$$ and test- $$-lock 將具有相同的 $$?

類似 here-doc 的<<-SCRIPT行為就像一個雙引號字元串,因為在其中處理了擴展。為防止這種情況,請引用分隔符:

$ cat <<EOF
1+1 = $((1+1))
EOF

1+1 = 2

對比

$ cat <<'EOF'
1+1 = $((1+1))
EOF

1+1 = $((1+1))

所以在這裡:

cat <<-SCRIPT >test-$$
       ...
       osType=$(grep -Po '^NAME="\K[^"]*' /etc/os-release)

grep命令在一個命令替換中,因為SCRIPT沒有被引用,所以它被處理,所以它在使用 here-doc 時執行。

另一方面,這裡:

cat <<-SCRIPT >test-$$
       #!/bin/bash
       rpm -q somepackage > test-$$
       rm test-$$-lock
       exit
   SCRIPT

沒有命令替換,所以沒有命令執行。該rpm -q somepackage部分只是文本。但是,如果使用不帶引號的分隔符,$$則 here-doc 內部將立即擴展為與輸出文件名稱中使用的值相同的值。也就是說,如果目前 shell 的 PID 為 1234,則該cat命令將創建test-1234包含該行的rpm -q somepackage > test-1234.

使用帶引號的分隔符,$$將保持原樣,結果將是名為test-1234contains 的文件rpm -q somepackage > test-$$。如果您現在test-1234作為腳本執行,那麼$$將會擴展,並且將使用shell 的 PID。它可能與創建文件時使用的值不同。

在任何情況下,$$inrpm .. > test-$$rm test-$$-lock都會擴展為相同的值。

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