質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.47%
bash

bash(Bourne-again-Shell)は sh(Bourne Shell)のインプリメンテーションに様々な機能が追加されたシェルです。LinuxやMac OS XではBashはデフォルトで導入されています。

Linux

Linuxは、Unixをベースにして開発されたオペレーティングシステムです。日本では「リナックス」と呼ばれています。 主にWebサーバやDNSサーバ、イントラネットなどのサーバ用OSとして利用されています。 上位500のスーパーコンピュータの90%以上はLinuxを使用しています。 携帯端末用のプラットフォームAndroidは、Linuxカーネル上に構築されています。

Q&A

解決済

1回答

504閲覧

Linuxのシェルスクリプトが正しく動かない

tada_tadaa

総合スコア111

bash

bash(Bourne-again-Shell)は sh(Bourne Shell)のインプリメンテーションに様々な機能が追加されたシェルです。LinuxやMac OS XではBashはデフォルトで導入されています。

Linux

Linuxは、Unixをベースにして開発されたオペレーティングシステムです。日本では「リナックス」と呼ばれています。 主にWebサーバやDNSサーバ、イントラネットなどのサーバ用OSとして利用されています。 上位500のスーパーコンピュータの90%以上はLinuxを使用しています。 携帯端末用のプラットフォームAndroidは、Linuxカーネル上に構築されています。

0グッド

0クリップ

投稿2024/02/28 09:17

編集2024/02/28 12:07

実現したいこと

Linuxのシェルスクリプトを正しく動くようにしたい

発生している問題・分からないこと

引数の先頭文字が小文字なら
the '引数文字列' is lower case.

引数の先頭文字が大文字なら
the '引数文字列' is upper case.

と表示されるはずが、引数の先頭の文字が大文字でも「lower case」のほうが出力される

エラーメッセージ

error

1[root@localhost bashTest]# bash -x case.bash A 2+ case "$1" in 3+ echo 'the '\''A'\'' is lower case.' 4the 'A' is lower case. 5[root@localhost bashTest]# bash -x case.bash a 6+ case "$1" in 7+ echo 'the '\''a'\'' is lower case.' 8the 'a' is lower case. 9[root@localhost bashTest]# bash -x case.bash @ 10+ case "$1" in 11+ echo 'the '\''@'\'' is not alphabet' 12the '@' is not alphabet 13[root@localhost bashTest]#

該当のソースコード

bash

1 1 2 2 case "$1" in 3 3 [a-z]*) 4 4 echo "the '$1' is lower case." 5 5 ;; 6 6 [A-Z]*) 7 7 echo "the '$1' is upper case." 8 8 ;; 9 9 *) 10 10 echo "the '$1' is not alphabet" 11 11 ;; 12 12 esac

試したこと・調べたこと

  • teratailやGoogle等で検索した
  • ソースコードを自分なりに変更した
  • 知人に聞いた
  • その他
上記の詳細・結果

bash -x case.bash A

sh -x case.bash A
を試したが両方とも「lower case」のほうが出力された

補足

centOS7

###追記
カレントディレクトリで「ls -la」「cat case.bash」「bash case.bash AA」を実行した結果です。確実にカレントディレクトリのスクリプトファイルの「case.bash」を実行しているように見えます。

[root@localhost bashTest]# ls -la
total 28
drwxrwxr-x 2 tada tada 121 Feb 28 18:38 .
drwxrwxr-x 4 tada tada 86 Feb 28 16:59 ..
-rw-rw-r-- 1 tada tada 41 Feb 28 17:17 args.bash
-rw-rw-r-- 1 tada tada 156 Feb 28 18:13 case.bash
-rw-rw-r-- 1 tada tada 46 Feb 28 18:21 for.bash
-rw-rw-r-- 1 tada tada 62 Feb 28 18:38 function.bash
-rwxrwxr-x 1 tada tada 44 Feb 28 17:00 hello.bash
-rw-rw-r-- 1 tada tada 168 Feb 28 17:37 if.bash
-rw-rw-r-- 1 tada tada 72 Feb 28 18:26 while.bash
[root@localhost bashTest]# cat case.bash

case "$1" in
[a-z])
echo "the '$1' is lower case."
;;
[A-Z]
)
echo "the '$1' is upper case."
;;
*)
echo "the '$1' is not alphabet"
;;
esac
[root@localhost bashTest]# bash case.bash AA
the 'AA' is lower case.
[root@localhost bashTest]#

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

melian

2024/02/28 09:28

Ubuntu Linux 23.10 上で bash version 5.2.15 と dash 0.5.12 で試してみましたが、どちらとも "the 'A' is upper case." と表示されました。
tada_tadaa

2024/02/28 09:34

今、再度確認してみましたが、やはり 「the 'A' is lower case.」 と表示されました
otn

2024/02/28 11:40

あり得るとすると、「実行しているつもりのコードと、実際に実行しているコードが違う」とかでしょうか。 cat case.bash は、期待通りの結果ですか?
tada_tadaa

2024/02/28 12:08

確実にカレントディレクトリの「case.bash」を実行しているであろう事を示すために、追記を書きました
bsdfan

2024/02/28 14:27

ロケール(LANG, LC_ALL, LC_COLLATE)はどうなっていますか? LC_ALL=C でやるとどうなりますか?
tada_tadaa

2024/02/28 15:26

localeコマンドを実行した結果は次の通りです。 [root@localhost ~]# locale 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= [root@localhost ~]# LC_ALL=C に設定する方法は分かりません。.bash_profileファイルに「LC_ALL=C」を適当な行に追記して、ログインし直したのですが、何も変わってないようなのでちゃんと設定されているかも分からないので、LC_ALL=C に設定する方法は分かりません。
melian

2024/02/28 16:17

CentOS7 にデフォルトでインストールされている bash のバージョンは 4.2 とのことなので、 http://ftp.gnu.org/gnu/bash/bash-4.2.tar.gz からソースコードをダウンロードしてビルドしてみました。そして bash-4.2 という名前にリネームして、cash.bash を実行してみました。 $ LC_COLLATE=en_US.UTF-8 ./bash-4.2 case.bash a the 'a' is lower case. $ LC_COLLATE=en_US.UTF-8 ./bash-4.2 case.bash A the 'A' is lower case. 前述の通り、最新の bash 5.2.15 では LC_COLLATE を設定しても "the 'A' is upper case." と表示されます。 なので、LC_COLLATE=C もしくは LC_COLLATE= に設定して実行すると "the 'A' is upper case." と表示されます。 $ LC_COLLATE=C ./bash-4.2 case.bash A the 'A' is upper case. $ LC_COLLATE= ./bash-4.2 case.bash A the 'A' is upper case. もしくは、[a-z] や [A-Z] を [[:lower:]] や [[:upper:]] に変更します。 case "$1" in [[:lower:]]*) echo "the '$1' is lower case." ;; [[:upper:]]*) echo "the '$1' is upper case." ;; *) echo "the '$1' is not alphabet" ;; esac
otn

2024/02/28 16:30 編集

localeのことを失念していました。localeが英語系(例えば en_US とか en_US.UTF-8)だと、英字順序は aAbBcC~~zZ のようになるので、 [a-z]は[aAbBcC~~xXyYz]と同じです。[A-Z]も[AbBbcC~~xXyYzZ]と同じです。 さらに、en_US.UTF-8 のように英字ユニコード系だと、全角英字 A や a もこの範囲に含まれてしまいます。その他の各国文字の英字も。 > LC_ALL=C に設定する方法は分かりません。 文字通りには、冒頭に、 export LC_ALL=C です。 範囲指定を使わずに[[:lower:]] [[:upper:]] のように「POSIXクラス」を書く手もあります。 これだとロケールが何であれ、小文字と大文字を区別できます。 ただし、ユニコード系のロケールだと、全角など各国のの A や a も、「英字以外」じゃなくて「英大文字」「英子文字」と判断されます。 ロケール C だと、英字と判断されるのは半角英字のみで、全角英字は[[:upper:]] [[;lower:]]にマッチしません。 あるいは、[ABCDEFGHIJKLMNOPQRSTUVWXYZ] と全部列挙すると列挙した文字にしかマッチしませんので、ロケールの影響は受けません。 ということで、対応方法としては、まず「全角英字をどう判断したいか」を決める必要があります。 「全角英字は必ず not alphabet にしたい」と言うことが無ければ、 export LC_ALL=C を書かずに、[[:lower:]] [[:upper:]] でしょうか。 この場合、全角英字が英字扱いされるかどうかは、ロケールがUTF-8かどうかに依存します。
otn

2024/02/29 14:51

ロケールの指摘は、melianさんなので、melianさんに回答を書いてもらい、それをベストアンサーにするのが良いと思います。 ずっとrootで作業していることからして「sshでなくコンソール作業かも」と推測できたかもしれません。 (コンソールだと /etc/profile.d/lang.sh 内で en_US か en_US.UTF-8 になる)
guest

回答1

0

ベストアンサー

ファイルは間違いなさそうですね。なお、コードを載せる時はコードブロックに書きましょう。*が「イタリック文字指定」と解釈されています。

あまりやらないことですが、Bashのshoptで、nocasematchがオンになっているのでしょう。
意味は文字通りですが、マッチの時に大文字小文字を区別しません。

Bash

1# これで今オンかオフかを表示する 2shopt nocasematch 3# オフにする 4shopt -u nocasematch

を冒頭に入れてみましょう。
デフォルトはオフなので、設定ファイルのどこかにshopt -s nocasematchがあると思われます。

なお、タイトルですが、

Linuxのシェルスクリプトが正しく動かない

ということはありません。あるのは、「Linuxのシェルスクリプトが自分の期待通り動かない」ということだけです。

投稿2024/02/28 12:31

編集2024/02/28 12:58
otn

総合スコア84635

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

tada_tadaa

2024/02/28 13:20

回答ありがとうございます。 スクリプトファイルの冒頭にご指摘の文を挿入しましたが、結果は変わらず「lower」の方が出力されました。 カレントディレクトリで「cat case.bash」等のコマンドを実行たときのコンソール画面の出力を下記に貼り付けます。 [root@localhost bashTest]# cat case.bash # これで今オンかオフかを表示する shopt nocasematch # オフにする shopt -u nocasematch case "$1" in [a-z]*) echo "the '$1' is lower case." ;; [A-Z]*) echo "the '$1' is upper case." ;; *) echo "the '$1' is not alphabet" ;; esac [root@localhost bashTest]# bash case.bash A nocasematch off the 'A' is lower case. [root@localhost bashTest]# sh case.bash A nocasematch off the 'A' is lower case. [root@localhost bashTest]# sh case.bash 8 nocasematch off the '8' is not alphabet [root@localhost bashTest]# sh case.bash a nocasematch off the 'a' is lower case. [root@localhost bashTest]#
tada_tadaa

2024/02/28 13:42

気になる現象があるのでコメントします。 「shopt -s nocasematch」でオンに設定してもコンソールには「nocasematch off」と出力されています。これが何か関係しているのかもしれないです。 [root@localhost bashTest]# cat case.bash # これで今オンかオフかを表示する shopt nocasematch # オンにする(-sでオン、-uでオフ) shopt -s nocasematch case "$1" in [a-z]*) echo "the '$1' is lower case." ;; [A-Z]*) echo "the '$1' is upper case." ;; *) echo "the '$1' is not alphabet" ;; esac [root@localhost bashTest]# bash case.bash A nocasematch off the 'A' is lower case. [root@localhost bashTest]#
otn

2024/02/28 13:46

nocasematch off ですか。これが on だと [a-z] が A にマッチするのですが。 [[ A == [a-z] ]] echo $? [[ a == [a-z] ]] echo $? で、どう表示されますか?2つ目は真なので 0 のはずですが。1つ目は?
otn

2024/02/28 14:11

> 「shopt -s nocasematch」でオンに設定してもコンソールには「nocasematch off」と出力されています。 コマンドラインで shopt -s nocasematch を実行してそのあとコマンドラインで shopt nocasematch を実行して off と表示されるということでしょうか?
tada_tadaa

2024/02/28 14:47

>コマンドラインで shopt -s nocasematch を実行してそのあとコマンドラインで shopt nocasematch を実行して off と表示されるということでしょうか? コマンドラインではなく、スクリプトファイル「case.bash」の冒頭に # これで今オンかオフかを表示する shopt nocasematch # オンにする(-sでオン、-uでオフ) shopt -s nocasematch を記入して、コンソールで [root@localhost bashTest]# bash case.bash A を実行したら nocasematch off が表示されたという意味です。最初にotn様が # これで今オンかオフかを表示する shopt nocasematch # オフにする shopt -u nocasematch の4行をスクリプトファイルの冒頭挿入すると良いとのアドバイスをされたので、その4行を挿入しました。 で、「shopt -u nocasematch」のオプションが「-u」でnocasematchが無効になる設定だったのですが、試しに僕が「shopt -s nocasematch」に書き換えて「-s」でnocasematchを有効になるように書き換えて、 [root@localhost bashTest]# bash case.bash A を実行したのですが、本来であればコンソール出力に nocasematch on と表示されそうな気がするのですが、相変わらず nocasematch off と出力されていて、オプションで有効になる設定をしたにもかかわらず、有効になってないようなので nocasematch に関連した機能が壊れてて、それでスクリプトファイルが、狙った通りに動いてくれないのではないかと推測しました。nocasematchの部分(大文字小文字を区別する機能)が壊れているんですかね?
tada_tadaa

2024/02/28 23:06

melian様のご指摘の通りにロケールを指定すると希望通りの出力が得られました。 コマンドプロンプトで [root@localhost bashTest]# export LC_ALL=C と入力すると期待通りの出力になります。 以下にコンソール画面での出力結果を貼り付けます。 [root@localhost bashTest]# export LC_ALL=C [root@localhost bashTest]# bash case.bash A nocasematch off the 'A' is upper case. [root@localhost bashTest]# export LC_ALL=en_US.UTF-8 [root@localhost bashTest]# bash case.bash A nocasematch off the 'A' is lower case. [root@localhost bashTest]# cat case.bash # これで今オンかオフかを表示する shopt nocasematch # オンにする(-sでオン、-uでオフ) shopt -u nocasematch case "$1" in [a-z]*) echo "the '$1' is lower case." ;; [A-Z]*) echo "the '$1' is upper case." ;; *) echo "the '$1' is not alphabet" ;; esac [root@localhost bashTest]# otn様が >localeのことを失念していました。localeが英語系(例えば en_US とか en_US.UTF-8)だと、英字順序は aAbBcC~~zZ のようになるので、 と、コメントされてたので、ロケールが「en_US.UTF-8」に設定されてたので [a-z]*) でも大文字のAが条件に適合されて echo "the '$1' is lower case." が実行されていたと思われます。 原因と解決方法が分かりました。 ありがとうございました。
tada_tadaa

2024/02/28 23:07

回答ありがとうございます。 試したところ問題が解決しました! ベストアンサーに選ばせていただきました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.47%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問