POSIXシェルで文字列計算変数を使用するには?

POSIXシェルで文字列計算変数を使用するには?

Ubuntuコンテナ内で実行されるスクリプトがあります。

#!/bin/sh

name=$(cat < /etc/os-release | grep "^NAME" | cut -d "=" -f 2)

if [ $name = "Ubuntu" ] 
then 
  echo "This should return"
else  
  echo "This is wrong"
fi

以下を実行してコンテナを起動します。

docker run -it -v $(pwd):/scripts ubuntu:latest /bin/sh /scripts/test.sh

私が受け取った出力は「This iswrong」です。これは間違っています。私のラップトップはUbuntuなので、$nameの出力が「Ubuntu」であることを知っていますが、これが起こる理由を見つけることができません。スクリプトにパスがあるのはなぜですか?コンテナ外のノートブックでも同じことを行います。

答え1

このファイルには、/etc/os-releaseシェル互換変数割り当てのリストが含まれています。シェルスクリプトで解析する必要はなく、関連変数を使用するだけsourceです。.

$ cat ex.sh
#!/bin/sh
. /etc/os-release
echo "$NAME"

$ ./ex.sh
Ubuntu

答え2

Debian では、この特定の行は次のようになります。

NAME="Debian GNU/Linux"

右側の引用符に注意してください。 Ubuntuでも使用できる場合、name引用符は特別なものではないため、文字通り引用符を受け取りますcut。別の問題は、文字列にスペースを含めることができることです。この場合、トークン化は文字列内の引用符なしの変数拡張に達し、[ $name = "Ubuntu" ]テストでエラーが発生する可能性があります。

このような問題を回避するには、変数拡張を引用し、比較文字列の周りにリテラル引用を追加します。

if [ "$name" = '"Ubuntu"' ]; then ...

または、文字列の先頭と末尾から引用符を削除し、name=${name#\"}; name=${name%\"}まだquoteを使用します"$name"

答え3

この特別なケースでは、次のようにスクリプトを単純化できます。

#!/bin/sh

if grep -q Ubuntu /etc/os-release; then
  echo "This should return"
else
  echo "This is wrong"
fi

grep、この-qオプションを渡すと何も印刷されませんが、文字列が見つかった場合はコード0で終了し、それ以外の場合はゼロ以外のコードで終了します。if結局、それが私たちが期待するものです。

答え4

シンプル

$ grep -q Ubuntu /etc/os-release && echo "This should return" || echo "This is wrong"

または

$ . /etc/os-release && echo "$NAME"

または、lsb_release次のコマンドを使用することもできます。

$ lsb_release -i -s

関連情報