プログラミング

一見違いがなさそうなBashの変数に隠れた文字コードを可視化する”cat -A”

一見、2つの変数は同一に見えるけど、ifで判定してみるとなぜかうまくいかない、ということがあります。
例えば、以下のような場合です。

2つの変数をechoしてみると、このように同一に見えます。

$ echo $md5_remote
8a32e4c5528d684ffc9c76899e4ec256
$ echo $md5_local
8a32e4c5528d684ffc9c76899e4ec256

https://yuis.xsrv.jp/images/ss/ShareX_ScreenShot_cf7bbaee-0950-4e7d-9111-ee9b60ab9631.png

こちらのほうが正確な出力が得られる書き方ですので、これも試してみます。しかし出力は同じです。

$ echo "${md5_remote}"
8a32e4c5528d684ffc9c76899e4ec256
$ echo "${md5_local}"
8a32e4c5528d684ffc9c76899e4ec256

https://yuis.xsrv.jp/images/ss/ShareX_ScreenShot_c4912fe0-e192-4c01-8f63-4da7dfbf7d95.png

ifでイコール判定をしてみても、やはりイコールではないと言われてしまいます。

if [[ "${md5_local}" == "${md5_remote}" ]]; 
then 
  echo y 
fi 

https://yuis.xsrv.jp/images/ss/ShareX_ScreenShot_625c58ca-57da-47b7-b205-3e8abfaa345f.png

こんなとき、cat -Aでファイルの隠れた文字コードを出力するのが便利な解決策です。

$ echo "${md5_remote}" | cat -A
8a32e4c5528d684ffc9c76899e4ec256^M$
$ echo "${md5_local}" | cat -A
8a32e4c5528d684ffc9c76899e4ec256$

https://yuis.xsrv.jp/images/ss/ShareX_ScreenShot_b94617d3-6304-47b3-819e-3078a9193235.png

このように、一見同一に見られた2つの変数は、実際は同一ではなかったことがわかります。

では、変数を同一のものとしてif判定するにはどうしたらよいのでしょうか。以下関数を使って、文字列の最初と最後の空白を取り除いてみましょう。PHPのtrimと同様の働きをします。

trim () 
{ 
    local var="$*";
    var="${var#"${var%%[![:space:]]*}"}";
    var="${var%"${var##*[![:space:]]}"}";
    echo -n "$var"
}

ここでtrimを使ってifのイコール判定をしてみます。


if [[ "$( trim "${md5_local}" )" == "$( trim "${md5_remote}" )" ]]; then echo y fi y

https://yuis.xsrv.jp/images/ss/ShareX_ScreenShot_084e781f-b052-41a8-985d-04cc9073662e.png

想定通りの結果が得られました。