実現したいこと
Linuxのsedコマンドを、utf-8の文字コードで正しく動くようにしたい。
文字コードがus-asciiのファイルは正しく動いた。文字コードによって動かなくなるのを未然に防ぐ対策法が知りたい。
発生している問題・分からないこと
hostaddr2とteratailという、文字コードが違うだけで内容が同じ二つのシェルスクリプトがあります。
hostaddr2を実行すると
[tada@linux shscript]$ ./hostaddr2 HOST=linux.tmiloweb.net HOST=linux.tmiloweb.net
と表示されますが、teratailを実行すると
[tada@linux shscript]$ ./teratail HOST=linux.tmiloweb.net HOST=linux
と表示されてちゃんと処理されている事がわかります。
二つのファイルの差異をdiffコマンドで確認すると
[tada@linux shscript]$ diff teratail hostaddr2 6c6 < HOST=`echo $HOST | sed 's/\..*//'` --- > HOST=`echo $HOST | sed 's/\..*//'`
と表示されたのですが、どう違うのか分からなかったので odコマンドでファイルをダンプしてみました。
[tada@linux shscript]$ od -t a teratail 0000000 # ! / b i n / s h nl nl H O S T = 0000020 $ { 1 : - ` h o s t n a m e ` } 0000040 nl e c h o sp " H O S T = $ H O S 0000060 T " nl nl H O S T = ` e c h o sp $ 0000100 H O S T sp | sp s e d sp ' s / \ . 0000120 . * / / ' ` nl e c h o sp " H O S 0000140 T = $ H O S T " nl nl 0000152 [tada@linux shscript]$ od -t a hostaddr2 0000000 # ! / b i n / s h nl nl H O S T = 0000020 $ { 1 : - ` h o s t n a m e ` } 0000040 nl e c h o sp " H O S T = $ H O S 0000060 T " nl nl H O S T = ` e c h o sp $ 0000100 H O S T sp | sp s e d sp ' s / B % 0000120 . . * / / ' ` nl e c h o sp " H O 0000140 S T = $ H O S T " nl nl 0000153 [tada@linux shscript]$
すると
sed 's/\..*//'`
の部分の「\」記号のところがファイルteratailの方では「\」で表示されているのに対して
ファイルhostaddr2の方では「B %」になっていました。見た目は同じなのに文字コードが違うよう
なので文字コードを確認してみると
[tada@linux shscript]$ file -i teratail teratail: text/x-shellscript; charset=us-ascii [tada@linux shscript]$ file -i hostaddr2 hostaddr2: text/x-shellscript; charset=utf-8
ファイルteratailの方ではus-asciiなのに対して、ファイルhostaddr2の方ではutf-8でした。
Linuxでは
多くのディストリビューションでは、文字コードとしてUTF-8を使用している
という説明を見たので、UTF-8でも問題なく動きそうなものですが、UTF-8で書かれたファイルhostaddr2はうまく動きませんでした。
ローカライゼーション系の環境変数を確認すると
LANG=en_US.UTF-8
で、UTF-8になってるので問題なさそうですが、なぜsedコマンドは正しく動かなかったのでしょうか?
また、こうした文字コードに関連した問題をシェルスクリプトで事前に防ぐ良い手段はどのような
ものでしょか?
お手数をおかけしますがよろしくお願いいたします。
該当のソースコード
sh
1#!/bin/sh 2 3# ファイルteratailの方 4 5HOST=${1:-`hostname`} 6echo "HOST=$HOST" 7 8HOST=`echo $HOST | sed 's/\..*//'` 9echo "HOST=$HOST"
sh
1#!/bin/sh 2 3# ファイルhostaddr2の方 4 5HOST=${1:-`hostname`} 6echo "HOST=$HOST" 7 8HOST=`echo $HOST | sed 's/\..*//'` 9echo "HOST=$HOST"
試したこと・調べたこと
- teratailやGoogle等で検索した
- ソースコードを自分なりに変更した
- 知人に聞いた
- その他
上記の詳細・結果
sedはutf-8ではうまく動かないのかと思い、検索して解決方法を探しましたが、そもそもLinuxはutf-8が採用されている事が多いとのことで、sedがutf-8でちゃんと動く方法がわかりませんでした。
補足
sedのバージョン
[tada@linux shscript]$ sed --version
sed (GNU sed) 4.2.2
使用しているシェル
[tada@linux shscript]$ echo $SHELL
/bin/bash
OSのバージョン
[tada@linux shscript]$ cat /etc/redhat-release
CentOS Linux release 7.9.2009 (Core)
ローカライゼーション系の環境変数
[tada@linux shscript]$ 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=
回答1件
あなたの回答
tips
プレビュー