グロブパターンから定義された変数によるバッシュ置換


10

以下の例は問題を説明しています。FILENAME置換を使用したときに、エコーされてパターンとして認識されたときに正しく印刷されるのはなぜですか?

#!/bin/bash

FILEPATH_WITH_GLOB="/home/user/file_*"
FILENAME=$(basename "$FILEPATH_WITH_GLOB")
echo $FILENAME                #file_1234
echo ${FILENAME:1:5}          #ile_*   <---why is this not ile_1

回答:


15
FILEPATH_WITH_GLOB="/home/user/file_*"

今、FILEPATH_WITH_GLOB含む/home/user/file_*

FILENAME=$(basename "$FILEPATH_WITH_GLOB")

FILENAMEが含まれていますfile_*

echo $FILENAME                #file_1234

$FILENAMEリストのコンテキストで引用符で囲まれていない場合、その展開はsplit + glob演算子を実行するため、一致するファイルのリストに展開されます。ファイル名の生成は、パラメーターの展開時に実行されます

echo ${FILENAME:1:5}          #ile_*   <---why is this not ile_1

リストコンテキストではまだ引用符で囲まれていないパラメーター展開であるため、split + globが実行されます。ただし、ここではile_*パターンはどのファイルとも一致しないため、代わりにそれ自体に展開されます。

ここでおそらくあなたが望むのは:

shopt -s nullglob # have globs expand to nothing when they don't match
set -- /home/user/file_* # expand that pattern into the list of matching 
                         # files in $1, $2...
for file do  # loop over them
  filename=$(basename -- "$file")
  printf '%s\n' "$filename" "${filename:1:5}"
done

または、配列に格納することもできます。

shopt -s nullglob
files=(/home/user/file_*)

最初の一致のみに関心がある場合、または一致が1つしかないことがわかっている場合は、そのファイルをとして参照できます$filesbash通常、配列のすべての要素の代わりに$files展開される厄介な動作${files[0]}(から継承された動作ksh、で修正zsh)を持っていますが、ここでは、これは一度は望ましい動作です。


説明してくれてありがとう。FILEPATH_WITH_GLOB=`echo /home/user/file_*` あなたの説明の後に回避策を講じることができました。
TheMeaningfulEngineer 2015年

@アラン、それはそれに対処する間違った方法です。ここでは配列を使用します。私の例のように、位置パラメータ($ 1、$ 2 ...)、またはどちらかbashのような配列:files=(/home/user/file_*)
ステファンChazelas

(そして、すべての大文字の変数は実際には環境変数のために予約されるechoべきであり、任意のデータのために使用されるべきではありません、変数はリストコンテキストで引用符で囲まれたままにされるべきではありません)。
ステファンChazelas
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.