Shell

和有什麼區別∗and∗一種nd* and@?

  • June 21, 2020

考慮以下程式碼:

foo () {
   echo $*
}

bar () {
   echo $@
}

foo 1 2 3 4
bar 1 2 3 4

它輸出:

1 2 3 4

1 2 3 4

我正在使用 Ksh88,但我也對其他常見的 shell 感興趣。如果您碰巧知道特定 shell 的任何特殊性,請務必提及它們。

我在 Solaris 的 Ksh 手冊頁中找到了以下內容:

的含義 $ * and $ @ 在不加引號或用作參數分配值或文件名時是相同的。但是,當用作命令參數時, $ * is equivalent to `` $ 1天 $ 2d…’’, where d is the first character of the IFS variable, whereas $ @ 相當於 $ 1 $ 2 ….

我嘗試修改IFS變數,但它沒有修改輸出。也許我做錯了什麼?

當它們沒有被引用時,它們是$*相同$@的。您不應該使用其中任何一個,因為一旦您有包含空格或萬用字元的參數,它們就會意外中斷。


"$*"擴展為一個單詞"$1c$2c..."。通常c是一個空格,但它實際上是 的第一個字元IFS,所以它可以是任何你選擇的字元。

我發現它唯一的好用處是:

用逗號連接參數(簡單版)

join1() {
   typeset IFS=,
   echo "$*"
}

join1 a b c   # => a,b,c

使用指定的分隔符連接參數(更好的版本)

join2() {
   typeset IFS=$1   # typeset makes a local variable in ksh (see footnote)
   shift
   echo "$*"
}

join2 + a b c   # => a+b+c

"$@"擴展為單獨的單詞:"$1" "$2" ...

這幾乎總是你想要的。它將每個位置參數擴展為一個單獨的單詞,這使得它非常適合接受命令行或函式參數,然後將它們傳遞給另一個命令或函式。"$1"並且因為它使用雙引號進行擴展,這意味著如果包含空格或星號 ( *) ,則內容不會中斷。


讓我們編寫一個名為的腳本svim,它vim使用sudo. 我們將做三個版本來說明差異。

svim1

#!/bin/sh
sudo vim $*

svim2

#!/bin/sh
sudo vim "$*"

svim3

#!/bin/sh
sudo vim "$@"

對於簡單的情況,所有這些都可以,例如不包含空格的單個文件名:

svim1 foo.txt             # == sudo vim foo.txt
svim2 foo.txt             # == sudo vim "foo.txt"
svim2 foo.txt             # == sudo vim "foo.txt"

但只有在您有多個參數時才能正常工作$*"$@"

svim1 foo.txt bar.txt     # == sudo vim foo.txt bar.txt
svim2 foo.txt bar.txt     # == sudo vim "foo.txt bar.txt"   # one file name!
svim3 foo.txt bar.txt     # == sudo vim "foo.txt" "bar.txt"

只有當你有包含空格的參數時才能正常工作"$*""$@"

svim1 "shopping list.txt" # == sudo vim shopping list.txt   # two file names!
svim2 "shopping list.txt" # == sudo vim "shopping list.txt"
svim3 "shopping list.txt" # == sudo vim "shopping list.txt"

所以只會"$@"一直正常工作。


typeset是如何在ksh(bash並改為ash使用local) 中創建局部變數。這意味著IFS當函式返回時將恢復到之前的值。IFS這很重要,因為如果設置為非標準,您之後執行的命令可能無法正常工作。

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