Case 文で大文字と小文字を区別する方法は?

Case 文で大文字と小文字を区別する方法は?

さびたシェルスクリプト技術を復習しようとしていますが、ケースの説明に問題があります。以下のプログラムの目的は、ユーザーが提供した文字列が大文字で始まるか小文字で始まるかを評価することです。

# practicing case statements
echo "enter a string"
read yourstring
echo -e "your string is $yourstring\n"

case "$yourstring" in
    [A-Z]* )
       echo "your string begins with a Capital Letter"
       ;; 
    [a-z]* )
       echo "your string begins with a lowercase letter"
       ;; 
    *)     
       echo "your string did not begin with an English letter"
       ;;
esac

myvar=nope

case $myvar in
   N*)
     echo "begins with CAPITAL 'N'"
     ;;
   n*)
     echo "begins with lowercase 'n'"
     ;;
   *)
     echo "hahahaha"
     ;;
esac

小文字で始まる文字列(引用符なしで「mystring」など)を入力すると、Case文は私の入力を最初のケースと一致させ、文字列が大文字で始まることを知らせます。私は明らかな構文や論理エラーを作成しているかどうかを確認するために2番目のケースの説明を作成しましたが(おそらくまだそうです)、同じ問題はありません。 2番目のケース構造は、$ myvarに含まれる文字列が小文字で始まることを正確に伝えます。

Caseステートメントの最初の行に$ yourstringを囲むために引用符を使用してみましたが、引用符を使用したくありませんでした。 「shopt」オプションについて読み、「nocasematch」がオフになっていることを確認しました。 (良い測定のために開いて再試行しましたが、最初のCase文でまだ正しい結果が得られませんでした。)また、shとbashを使用してスクリプトを実行してみましたが、出力は同じでした。 (実行ビットを設定していないため、「sh ./case1.sh」と「bash ./case1.sh」を使用して明示的にシェルを呼び出しました。ファイルをコピーして新しいファイルに実行ビットを設定しても計算。 )

「-x」デバッグオプションを使用してシェルを実行すると、出力される内容はすべて理解できませんが、出力は最初の「case」行で最初のパターンの後にコマンドを実行するシェルが進行していることを示しています。私はこれを入力文字列と一致する最初のパターンとして解釈しますが、理由はわかりません。

最初の2つのモード(および対応するコマンド)の順序を切り替えると、Caseステートメントは小文字で成功しますが、「MYSTRING」が小文字で始まると誤って報告されます。すべての文字はパターンで最初に表示される文字と一致することが検出されるため、論理エラーがあるようですが...何がわかりません。

unix.comでは、「小文字と大文字のテストは[az]と[AZ]です。一部のロケールおよび/またはLinuxディストリビューションでは機能しなくなりました。https://www.unix.com/shell-programming-and-scripting-128929-example-switch-case-bash.html)もちろん、文字の範囲を[[:upper:]]と[[:lower:]]に置き換えることで問題を解決しました。

私はFedora 31を使用しており、ロケール出力は次のようになります。

LANG=en_US.UTF-8
LC_CTYPE="en_US.UTF-8" 
LC_NUMERIC="en_US.UTF-8" 
LC_TIME="en_US.UTF-8" 
LC_COLLATE="en_US.UTF-8" 
LC_MONETARY="en_US.UTF-8" 
LC_MESSAGES="en_US.UTF-8" 
LC_PAPER="en_US.UTF-8" 
LC_NAME="en_US.UTF-8" 
LC_ADDRESS="en_US.UTF-8" 
LC_TELEPHONE="en_US.UTF-8" 
LC_MEASUREMENT="en_US.UTF-8" 
LC_IDENTIFICATION="en_US.UTF-8" 
LC_ALL= 

文字の範囲を理解していないか、Caseステートメントでパターンマッチングがどのように機能するかを理解していないか、デフォルトのシェル機能が変更されたのか(そしてその理由は何ですか?)疑問に思います。誰もが忍耐を持って説明をしてくれたらとても感謝します。また、喜んで文書を読んでみましょう。ありがとうございます!

ベストアンサー1

間違いなく他の人がその場に代わることができるというのは簡単な答えです。

文字セットの順序は、使用されるロケールによって異なります。ロケールの概念は、さまざまな民族グループとさまざまな言語をサポートするために導入されました。出力からわかるように、localeデータの並べ替えだけでなく、いくつかの異なる領域が解決されました。

あなたの場合はアメリカであり、並べ替えと整理の目的で、アルファベットはAaBbCc ... ZzまたはA = a、B = b、C = cなどです(何かを忘れており、コンピュータにないため、次のいずれかを確認できます)。それらを)。ロケールは複雑で、一部のロケールには並べ替えと照合には表示されない文字が含まれる場合があります。同じ文字でも、使用されるロケールによって異なるように並べ替えることができます。

見つかったように小文字を識別する正しい方法は[[:lower:]]、必要に応じてアクセント文字を含め、他のアルファベット(ギリシャ語、キリル文字など)の小文字も含めます。

デフォルトのソートが必要な場合は、設定を使用してアプリケーションごとまたはコマンド別に復元できますLC_ALL=C。人間が作った例を挙げると、

grep some_pattern | LC_ALL=C sort | nl

おすすめ記事