単語拡張とパス名拡張をテストする簡単なスクリプト

単語拡張とパス名拡張をテストする簡単なスクリプト

私が読んだ後、内容を確認しようとしています。ここ:

シェルは、私たちが説明するすべての種類の拡張を順番に実行することを覚えておくことが重要です。これは、パス名拡張の前に単語拡張が実行されることを意味します。したがって、拡張パスの結果を繰り返すと、その結果に対してトークン化は行われません。

私は上記の引用符を単語とパス名の拡張操作の順序について確認する非常に簡単なスクリプトを書いています。

$ 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"で区切ります。これが噴射です。引用符が分割されるのを防ぐ方法に注意してください。appleorangepassion fruitpassion 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'

それで何が起こりましたか?

  1. 変数$words分ける単語に変換された値$IFS。結果はzy.xlsxおよび3つの単語です*.xlsx

  2. 次に、3つの単語のそれぞれがパス拡張されます。これはパスに拡張できず、代わりに合計になるため、そのまま残り、x変更されません。y.xlsx*.xlsxx y.xlsxCCIE-Collaboration-v3-Learning-Matrix.xlsx

著者が言おうとしているのは、シェルがandに*.xlsx展開されたときにx y.xlsxすでに単語の区切りが発生しているため、単語の区切りがなくなり、スペースが含まれているにもかかわらずまだ単一の単語として扱われていることです。CCIE-Collaboration-v3-Learning-Matrix.xlsxx y.xlsx


混乱しているため、この回答の最初のバージョンは間違っています。トークン化噴射で。

おすすめ記事