私が読んだ後、内容を確認しようとしています。ここ:
シェルは、私たちが説明するすべての種類の拡張を順番に実行することを覚えておくことが重要です。これは、パス名拡張の前に単語拡張が実行されることを意味します。したがって、拡張パスの結果を繰り返すと、その結果に対してトークン化は行われません。
私は上記の引用符を単語とパス名の拡張操作の順序について確認する非常に簡単なスクリプトを書いています。
$ cat test.sh
for path in /home/john/Downloads/*.xlsx
do
echo "${path}"
done
結果
$ ./test.sh
/home/john/Downloads/CCIE-Collaboration-v3-Learning-Matrix.xlsx
/home/john/Downloads/x y.xlsx
私が知っている限り、単語拡張はパス拡張の前に起こり、これを実証するためにこれと非常によく似たスクリプトを使用しました。しかし、この例がどのように説明されているのか本当に理解していませんか?私が知る限り、「path」は、その変数がパスを識別した後に$ pathになる変数です。それでは、拡張と見なされる単語を見ることができないので、一体単語拡張がどこにあるのでしょうか。
明確にするために最初の反復を実行すると、$ pathは "/home/john/Downloads/*.xlsx"をチェックするまで空になり、この時点では "/home/john/Downloads/CCIE-Collaboration"として定義されます。 v3-Learning-Matrix.xlsx"これは最初のエントリであるため、この時点で$ pathが定義されており、単語拡張を適用する機会はありません(たとえば、実際のパス名が定義される前であると言う場合)。適用 "null"で)?
答え1
作家が書くとき単語拡張、彼らはページの他の場所ではこの用語を使用しません(しかし私が知っている限り、それは実際には完全に正確です。POSIX仕様を参照してください)ここ)、彼らは「単語分割」と呼ばれる分割操作を参照しているようです。これは、シェルが変数値(通常はスペース、タブ、改行に設定されている)に基づいて$IFS
分割されるプロセスです。たとえば、次のスクリプトを考えてみましょう(ここ、これは良い参考資料であるため、お読みください。
#!/bin/sh -
printf "%d args:" "$#"
[ "$#" -eq 0 ] || printf " <%s>" "$@"
echo
スクリプトは単に引数を印刷し、引数が単語にどのように分割されるかを示します。別の入力で実行してみてください。
$ foo.sh apple orange "passion fruit"
3 args: <apple> <orange> <passion fruit>
ここで、文字列は3つの「単語」、apple orange "passion fruit"
で区切ります。これが噴射です。引用符が分割されるのを防ぐ方法に注意してください。apple
orange
passion fruit
passion fruit
今の記事に示すように、順序が重要です。 「拡張」セクションを読むとバッシュマニュアル、あなたは見つけるでしょう:
拡張順序は、中かっこ拡張、引数と変数拡張、算術拡張、コマンド置換(左から右へ)です。
ここで重要なのは、上記のトークン化がファイル名(パス)拡張の前に発生することです。あなたの誤解はここにあります:
明確にするために最初の反復を実行すると、$ pathは "/home/john/Downloads/*.xlsx"をチェックするまで空になり、この時点では "/home/john/Downloads/CCIE-Collaboration"として定義されます。これは、「v3-Learning-Matrix.xlsx」は $path が定義される最初の項目であるためです。
いいえ、$path
この時点で定義されており/home/john/Downloads/CCIE-Collaboration-v3-Learning-Matrix.xlsx
、ループ内で拡張されず、ループが開始される前に拡張されます。私たちは、現在持っているスクリプトとは少し異なるスクリプトを使用して、トークン化とパス名拡張の2つを区別できます。
#!/bin/bash
words="x y.xlsx *.xlsx"
for word in $words; do
echo "word is '$word'"
done
次のディレクトリでスクリプトを試してください。
$ ls -1
CCIE-Collaboration-v3-Learning-Matrix.xlsx
'x y.xlsx'
出力は次のとおりです
$ foo.sh
word is 'x'
word is 'y.xlsx'
word is 'CCIE-Collaboration-v3-Learning-Matrix.xlsx'
word is 'x y.xlsx'
それで何が起こりましたか?
変数
$words
は分ける単語に変換された値$IFS
。結果はz
、y.xlsx
および3つの単語です*.xlsx
。次に、3つの単語のそれぞれがパス拡張されます。これはパスに拡張できず、代わりに合計になるため、そのまま残り、
x
変更されません。y.xlsx
*.xlsx
x y.xlsx
CCIE-Collaboration-v3-Learning-Matrix.xlsx
著者が言おうとしているのは、シェルがandに*.xlsx
展開されたときにx y.xlsx
すでに単語の区切りが発生しているため、単語の区切りがなくなり、スペースが含まれているにもかかわらずまだ単一の単語として扱われていることです。CCIE-Collaboration-v3-Learning-Matrix.xlsx
x y.xlsx
混乱しているため、この回答の最初のバージョンは間違っています。トークン化噴射で。
答え2
私は彼らが説明したいのですが、シェルがand(「パス名拡張」)/home/john/Downloads/*.xlsx
に拡張された後にそれを再度、and(「単語分割」に分割しようとしないことです)。/home/john/Downloads/CCIE-Collaboration-v3-Learning-Matrix.xlsx
/home/john/Downloads/x y.xlsx
/home/john/Downloads/CCIE-Collaboration-v3-Learning-Matrix.xlsx
/home/john/Downloads/x
y.xlsx
いいえ「単語拡張」)。これはfor
すべて、ループが変数に値を割り当てる前に発生します。したがって、パス名拡張の結果に対してトークン化を実行すると、ループは私たちが見ることができる3つの値ではなく2つの値に対してのみ繰り返されます。これらのどれも循環系で起こるものとは何の関係もありません。
一方、がある場合、for i in $(echo a b c)
シェルはコマンド置換の結果をトークン化し、結果のループ反復ではなく3つのループ反復が表示されますfor i in "$(echo a b c)"
。
答え3
この文章「これは、パス名拡張の前に単語拡張が行われることを意味します。」引用文の内容は、ソースが「単語拡張」とは何かを定義しないため意味がありません。次の文では、ページの前半で説明した噴射について言及し、その意味になることがあります。だから、「単語拡張」というフレーズを無視してください。この場合は間違っています。シンプルでシンプルです。。
次の引用はより意味があります。
したがって、拡張パスの結果を繰り返すと、その結果に対してトークン化は行われません。
空のディレクトリに2つのファイルを作成し、次の繰り返しのoneword
状況を検討してください。two words
./*
touch 'oneword' 'two words'
i=0
for f in ./*; do
printf "%d: %s\n" "$i" "$f"
i=$(( i+1 ))
done
以下の出力は、ループが2つの項目を繰り返すことを示しています./oneword
。./two words
これは、ファイル名を分割しなくてもパス名拡張の直接の結果です。
0: ./oneword
1: ./two words
噴射が発生した場合後ろにパス名拡張を実行すると、2番目のファイル名がにさらに分割され、./two
words
ループが合計3回実行されます。 (デフォルト値を想定しますIFS
。)
上記のQは続きます
私が知る限り、単語拡張はパス拡張の前に起こり、これを実証するためにこれと非常によく似たスクリプトを使用しました。
しかし、上記のように、これは意味がありません。あなたが引用したソースは、「単語拡張」が何を意味するのかを定義しません。それはあなたのせいではありません。あなたは用語の一貫性を維持できないソースのために混乱を経験しました。
今技術的に言えば、POSIX仕様すべてのチルダ拡張、パラメータ拡張、コマンド置換、算術拡張、フィールド分割(しばしば単語分割と呼ばれる)、パス名/ファイル名拡張、および引用符を削除するには、「単語拡張」という句を使用します。しかし、あなたのソースがそのフレーズを使用する文脈は、その定義と一致しません。単語拡張は、パス拡張「以前」には発生できません。なぜなら、単語拡張によるものです。含むパス拡張。
では、地球という言葉の拡張はどこから出るのでしょうか?拡張とみなされる言葉がまったく見えないからです。
繰り返しますが、あなたが意味するものによって異なります。 POSIXの意味の「単語の分離」はほとんどすべてを扱うので、Qのスクリプトにはファイル名/home/john/Downloads/*.xlsx
に「単語拡張」(パス名拡張)があり、"${path}"
現在のファイル名に「単語拡張」(パラメータ拡張)があります。変数の値ですpath
。 (上記のスクリプトにも算術拡張があります。)