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

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

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

sedとは、POSIX環境のために作られたコマンドラインエディタです。sedは編集スクリプトの指示のもとに複数のファイルを編集し、標準出力にその結果を出力します。

Linux

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

sh

shは、UNIX系OSのシェル操作の1つであり、最も基本的なシェルのことです。

Q&A

解決済

1回答

300閲覧

Linuxでsedコマンドが、utf-8の文字コードのファイルで正しく動かないようだ

tada_tadaa

総合スコア111

sed

sedとは、POSIX環境のために作られたコマンドラインエディタです。sedは編集スクリプトの指示のもとに複数のファイルを編集し、標準出力にその結果を出力します。

Linux

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

sh

shは、UNIX系OSのシェル操作の1つであり、最も基本的なシェルのことです。

0グッド

0クリップ

投稿2024/03/16 01:12

実現したいこと

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=

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

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

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

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

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

tada_tadaa

2024/03/16 06:54

文字コードがUTF-8内の円記号を簡単に見つける方法として grep -F $'\xc2\xa5' <ファイル名> が使えるようです。 Q. Linuxで文字コードがUTF-8のファイルに「\」記号(文字コード 0xC2A5)をスマートに検索して見つけ出す方法を知りたい https://teratail.com/questions/s0hrgngf9o0hbm
guest

回答1

0

ベストアンサー

hostaddr2には半角円記号である ¥が含まれています。
バックスラッシュである \ と、半角円記号である ¥は別の文字ですので、エスケープとして処理できていないのが原因です。

od -tx1a <ファイル名> などで見ると確認しやすいかと思います。

投稿2024/03/16 01:34

Eggpan

総合スコア2729

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

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

Eggpan

2024/03/16 01:37

Macだと ¥ のキーを押すとデフォルトで半角円記号がタイプされてしまうので、プログラミング用途で使う場合はバックスラッシュをデフォルトにしておいたほうが使い勝手が良いかも知れません。 https://qiita.com/minattoo/items/1ce084614246764187c3
hiroki-o

2024/03/16 02:44

補足すると、US-ASCIIの0x5CとUTF-8の0xC2A5の違いです。
tada_tadaa

2024/03/16 03:06

原因がわかりました。 ¥記号 と / バックスラッシュ は同一のものと思ってましたが、UTF-8の \記号が 見た目がバックスラッシュとして表示されることがあり、両者は区別されるものだという事がわかりました。 ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問