shで文字列の判定がうまくいかない part2

Linux
スポンサーリンク

問題のスクリプト

こんにちは、なたでです!

前回の「shで文字列の判定がうまくいかない part1」に続いて
引き続き、問題のスクリプトを展開します。(早い)

#!/bin/sh

# 2つの文字列を記載
str1="A B"
str2="A  B"

# それぞれ別のファイル名
file1="file1.txt"
file2="file2.txt"

# 一度保存する
echo ${str1} > ${file1}
echo ${str2} > ${file2}

# 読み込む
str1=`cat ${file1}`
str2=`cat ${file2}`

# 文字列の比較
if [ "${str1}" = "${str2}" ]; then
	echo "一致してるよ!"
else
	echo "一致してないよ!"
fi

さあ、みなさん!
上記のスクリプトを実行するとどうなるでしょう!

ふっふっふ。

さて、先ほどのスクリプトを実行しましょう。

結果は、

一致してるよ!

どうでしたか、
予想はあっていましたでしょうか。

スクリプトのどこに問題があるのか

一見スクリプトは、問題なく見えます。
そして、”A B”と”A  B”を比較したので、
「一致してないよ!」と表示されるような感じもします。

では、なぜ「一致してるよ!」とでたのでしょうか。
勿体ぶってもしょうがないので種明かしします。
保存したはずの「file1.txt」と「file2.txt」のテキストの内容を見てみてください。

◆ file1.txt の内容

A B

◆ file2.txt の内容

A B

そうです、file1もfile2も両方とも同じ”A B”になっているのです。
2つのスペースはどこいったのでしょうか……

実は以下のコード

#!/bin/sh

# 2つの文字列を記載
str1="A B"
str2="A  B"

# それぞれ別のファイル名
file1="file1.txt"
file2="file2.txt"

# 一度保存する
echo ${str1} > ${file1}
echo ${str2} > ${file2}

このコードは実行時は次のようになります。

#!/bin/sh

# 一度保存する
echo A B > file1.txt
echo A  B > file2.txt

ここでポイントとなっているのが、

echo A B
echo A  B

という echo です。

実際に実行してみると、この時点で2つのスペースは消えます。

> echo A B
A B
> echo A  B
A B

なぜ消えてしまうのかいうと、
echo A  B は、echo プロセスに対して、
引数1にA、引数2にBを渡すという意味になり、
echo は渡された引数(引数1と引数2)を、
半角スペースで結合した文字を表示ということになります。

つまり、半角スペースは引数を分けるための
デリミタ(区切り文字)として利用されたということなのです。

解決策と結論

解決策として半角スペースをデリミタ(区切り文字)として認識させないように
ダブルクォーテーションでくくる方法があります。

> echo "A B"
A B
> echo "A  B"
A  B

最初のスクリプトを直してみましょう。

#!/bin/sh

# 2つの文字列を記載
str1="A B"
str2="A  B"

# それぞれ別のファイル名
file1="file1.txt"
file2="file2.txt"

# 一度保存する
echo "${str1}" > "${file1}"
echo "${str2}" > "${file2}"

# 読み込む
str1=`cat "${file1}"`
str2=`cat "${file2}"`

# 文字列の比較
if [ "${str1}" = "${str2}" ]; then
	echo "一致してるよ!"
else
	echo "一致してないよ!"
fi

文字列には半角スペースが含まれる可能性を加味し、
ダブルクォーテーションでくくることが大事なのです!

ちなみにこれを解決する策としてはダブルクォーテーションで囲う以外に、
IFS(Internal Field Separator)という環境変数を変更してしまうという手もあります。

#!/bin/sh

# IFS を:に変更する
oldifs=${IFS}
IFS=:

# 2つの文字列を記載
str1="A B"
str2="A  B"

# それぞれ別のファイル名
file1="file1.txt"
file2="file2.txt"

# 一度保存する
echo ${str1} > ${file1}
echo ${str2} > ${file2}

# 読み込む
str1=`cat ${file1}`
str2=`cat ${file2}`

# 文字列の比較
if [ "${str1}" = "${str2}" ]; then
	echo "一致してるよ!"
else
	echo "一致してないよ!"
fi

# IFS を元に戻す
IFS=${oldifs}

以上。

本当は怖いshでの文字列操作でした。
最後まで読んでいただき、ありがとうございます!

コメント

タイトルとURLをコピーしました