通常、$@
$ 0を除くすべてのパラメータを表すために使用します。しかし、$@
データ構造が何であるかわかりません。
$*
二重引用符が含まれている場合、動作が異なるのはなぜですか?誰でも通訳者レベルの説明を提供できますか?
forループで繰り返すことができるので、配列のように見えます。ただし、これはsimpleと同じように機能しますecho $@
。配列の場合、最初の要素のみが表示されます。シェルの制限により、実行する実験コードを作成できなくなります。
間の違いこの投稿:この文書は、$@
の動作がの動作と異なることを示しています$*
。しかし、データ型が混乱しています$@
。 Pythonなどの解釈言語であるShellは、一連の基本型の観点からデータを表現する必要があります。つまり、$@がコンピュータのメモリにどのように保存されるかを知りたいのです。
文字列ですか、複数行の文字列ですか、それとも配列ですか?
唯一のデータ型の場合、カスタム変数をその型のインスタンスとして定義できますか?
答え1
これはBourneシェルハッキングから始まった。 Bourneシェルでは、for
IFS単語分割(トークン化後)は、リストコンテキスト(コマンドライン引数または繰り返し単語)のすべての単語に対して実行されます。あなたが持っているなら:
IFS=i var=file2.txt
edit file.txt $var
2行目は3つの単語でタグ付けされ$var
拡張され、3つの単語すべてに対して分割+globが行われるので、結局、、、、を引数としてed
使用して実行することになります。t
f
le.txt
f
le2.txt
その一部を引用すると、分割+グローブを防ぐことができます。 Bourneシェルはもともと内部的に8番目のビットを設定し、どの文字が引用されたかを覚えていました(後でUnixが8ビットに整頓されたときに変更されましたが、シェルはまだどのバイトが引用されているのかを覚えているのと同様のことをしました)。
両方の間にスペースがある位置パラメーターの連結$*
です。$@
ただし、$@
二重引用符内にある場合は特別に処理されます。$1
含まれている場合は、foo bar
次のように展開されます。$2
baz
"$@"
foo bar baz
^^^^^^^ ^^^
(^
上記のsはビット8が設定されている文字を表します。)ここで、最初のスペースは引用符付きですが(ビット8が設定されている)、2番目のスペース(単語間に追加されたスペース)は引用符ではありません。
IFS分割は引数の分離を担当します($IFS
デフォルトでは空白文字と見なされます)。これは$*
以前のバージョンのMasheyシェルの拡張方法と似ています(それ自体はThomsonシェルに基づいていましたが、Bourneシェルは最初から作成されました)。
これは、Bourneシェルで位置引数のリストが空である理由を説明します(空の位置パラメータで"$@"
問題を解決する必要がありますか?)。${1+"$@"}
空白文字が含まれていないと効果はありません"$@"
。$IFS
目的は、引数リストを他のコマンドにそのまま渡すことです。ただし、これは$IFS
空のリスト、空の要素、または空白が含まれていないと正しく機能しません(最初の2つの問題は最終バージョンで最終的に修正されました)。
POSIX仕様の基盤となるKornシェルは、この動作をさまざまな方法で変更します。
- IFS分割は、引用符なしの拡張結果に対してのみ実行されます(
edit
上記の例のように文字通りの単語では実行されません)。file.txt
$*
空の$@
場合は最初の文字またはスペースで連結されますが、引用符付き演算子の場合はBourneシェルのように連結演算子が引用符解除され、引用符付きの場合は空白の場合は区切り文字ではなく位置引数が追加されます。$IFS
$IFS
"$@"
"$*"
IFS
- 配列のサポートを追加して
${array[@]}
${array[*]}
Bourneを連想させますが、$*
インデックス$@
1の代わりに0から始まり、希薄です(連想配列に似ています)。つまり、$@
実際には ksh 配列として処理できないことを意味します (csh
//rc
でここで / は通常の配列です)。zsh
fish
yash
$argv
$*
- 空の要素は保持されます。
"$@"
0 の場合、空の$#
文字列ではなく空の文字列に展開されます。"$@"
これは、空でない場合は空白がない場合に有効です。空の場合、ワイルドカードなしで引用符を持たない文字列は単一の引数に展開されます(位置引数はスペースで連結されています)。$IFS
IFS
$*
$IFS
ksh93は上記の残りの問題を解決します。 ksh93では、 の値に関係なく、分離された位置引数リストに展開され、次にリスト$*
コンテキストでさらに分割+グローブ+中括弧が拡張され、最初と関連付けられます。$@
$IFS
$*
バイト(文字ではない)ofは、$IFS
値"$@"
に関係なくリストコンテキストの位置引数リストに展開されます$IFS
。var=$@
in のような非リストコンテキストでは、$@
の値が何であれ空白に関連付けられます$IFS
。
bash
アレイはkshアレイの後に設計されています。違いは次のとおりです。
- 引用符で囲まれていない拡張中は中括弧拡張はありません。
- の最初の文字は
$IFS
forバイトを置き換えます。 $*
リスト以外のコンテキストでnullが引用されていない場合、拡張などのいくつかのコーナーケースの違いがあります$IFS
。
POSIX仕様は非常にあいまいでしたが、今ではbashの動作をある程度指定します。
ksh
次の点で通常の配列とは異なりますbash
。
- インデックスはゼロではなく1から始まります(インクルードを除外します
"${@:0}"
($0
位置引数ではなく、シェルと関数を定義する方法によって関数名が指定または指定されていません))。 - 要素を個別に割り当てることはできません。
- 希薄ではなく、要素を個別に設定解除することはできません。
shift
使用できます。
配列がzsh
通常の配列の場合は、通常の配列として扱われます(まれではなく、ksh / bashを除く他のすべてのシェルでインデックスが1から始まります)。 (互換性のために)エイリアスがあります。 orと同じです(引数はofの最初の文字に関連付けられますが、リストコンテキストでは別々に保持されます)。コーエンと類似または特殊加工された製品です。yash
$*
zsh
$argv
csh
$*
$argv
${argv[*]}
$IFS
"$@"
"${argv[@]}"
"${*[@]}"}
答え2
$@
しかし、データ構造が何であるかわかりません。
これは、位置パラメーターの値に拡張できる特殊パラメーターです。しかし、用語が難しいです。
位置引数をaの一部として考えることができるので、独立してアクセスでき、連続した自然数で名前を付けることができる$@
さまざまな要素($1
、...)があります。$2
これは一般に配列として知られている。
しかし、構文は少し奇妙で制限的です。配列の個々の要素は個別に変更できません。代わりに、すべてを一度に設定する必要があります。 (set -- "$@" foo
追加された値を使用することも、set -- "${@:1:2}" foo "${@:3}"
中間に値を追加することもできますが、どちらの場合も結果リスト全体を作成する必要があります。)
$*
二重引用符を含めるときとは異なる動作をするのはなぜですか?
彼らの行動が異なって定義されているからです。
ただし、これはsimpleと同じように機能します
echo $@
。配列の場合、最初の要素のみが表示されます。
a=(foo bar asdf); echo $a
単に出力を意味する場合、foo
これは主にシェル構文の珍しい点であり、kshスタイルの名前付き配列は位置引数と$@
. Plain$a
は同じであるため、配列であれ単純なスカラー変数で${a[0]}
あれ、単一のスカラー値に対して以前のバージョンと互換性のある意味を持ちます。a
@
リスト全体を参照するシンボルは、名前付き配列と共に再使用され、これがリスト"${a[@]}"
全体を取得する方法です。名前付き配列と比較してwithを使用すると、不要な中かっこ、角かっこ$@
、名前は省略されます。
つまり、
$@
コンピュータのメモリにどのように保存されるのかを知りたいのです。
これは実装によって異なり、関心のある特定のシェルのソースコードを調べる必要があります。
文字列ですか、複数行の文字列ですか、それとも配列ですか?
主に配列です。 kshスタイルの名前付き配列とは異なり、連続した整数だけでなく、負以外の任意の整数をインデックスとして持つこともできます$@
。 (つまり、名前付き配列は希薄である可能性があります。たとえば、indexes 、、、1
with 、および欠落などを持つことができます。これは位置引数では不可能です。)3
4
0
2
他の要素に拡張できるため、単一の文字列ではなく、通常の変数または位置引数のいずれか(要素$@
)に改行文字を含めることができるため、line要素の呼び出しも正しくありません。
唯一のデータ型の場合、カスタム変数をその型のインスタンスとして定義できますか?
いいえ。ただし、名前付き配列がより役に立つ可能性があります。