私はこのフラグメントを持っています:その背後にあるロジックは、ユーザーが-sの後に単語(-sdogなど)を入力したいということです。しかし、これはうまくいきません。
read -rp 'choose: ' choice
case $choice in
-a) echo you chose a;;
-s [a-z]+) echo you chose the word ${choice#"-s "};;
esac
とても感謝しています! ! !
答え1
を使用して2つの単語を読み取るには、read
2つの変数を使用します。
read -r -p 'Enter "-a" or "-s <word>": ' opt word
case $opt in
-a)
echo 'You picked "-a"'
;;
-s)
printf 'You picked "-s" with the word "%s"\n' "$word"
;;
*)
echo 'You picked neither "-a" nor "-s <word>"'
esac
コードが機能しない理由は、拡張正規表現をパターン(-s [a-z]+
)として使用しているためです。このステートメントで使用されるパターンは、ファイル名のcase
ワイルドカードパターンです。それらは似ていますが、同じではありません。ワイルドカードパターンは、正規表現パターンで使用されているのと同じタイプの「反復修飾子」()を受け入れません+
。
ワイルドカードパターンを使用するには、を使用できます'-s '[a-z]*
。つまり、「文字列-s
の後に小文字を使用して、何^-s [a-z].*
"(正規表現と同じ).
答え2
空白文字をエスケープする必要があります(例:回答前の質問)。
Bashはこれを「複数回発生」ではなく+
文字通り解釈します。+
Bashのパターンマッチング演算子は正規表現とは異なります。 1つ以上の項目を一致させるには、「拡張ワイルドカード」extglob
シェルオプションを有効にしてその+(...)
パターンを使用できます。
[a-z]
範囲式が小文字のみを一致させるには(ロケールLC_COLLATE
または設定によって異なります)、シェルオプションを有効にすることもLC_ALL
できます。globasciiranges
shopt -s extglob
shopt -s globasciiranges
read -rp 'choose: ' choice
case $choice in
-a)
echo "you chose a"
;;
-s\ +([a-z]))
echo "you chose the word \"${choice#-s }\""
;;
*) echo "unknown choice \"$choice\""
esac
関連:
- パターンマッチング(Bashリファレンスマニュアル)
答え3
…)
Caseステートメントには(引用符なし)スペースを含めることはできません。
したがって、引用する必要があります:\
、" "
または' '
:
また、Case 文のマッチングは正規表現ではなくパターンで行われます。+
内部ではないパターンマッチング、only*
ですが、これは最後の要素を繰り返すという意味ではなく、「すべての文字のすべての文字」を繰り返すという意味です。あなたの[a-z]+
目的は、小文字のみで構成された単語を一致させることを前提としています。より単純なパターンマッチング文字列に同じ内容を書き込むことは不可能です。実行できる操作は次のとおりです。
read -rp 'choose: ' choice
case $choice in
-a) echo "you chose a";;
-s\ *[^a-z]*) echo "not a valid word selected";;
-s\ *) echo "you chose the word ${choice#"-s "}";;
*) echo "no choice made";;
esac