設定ファイルに全角スペースやノーブレークスペースが混入していても、テキストエディタ上では見分けがつかないことがあります。「設定内容は合っているはずなのに構文エラーが出る」「サービスが正常に起動しない」といったトラブルの原因がこれらの不可視文字だったというケースは少なくありません。この記事では、grep で混入箇所を特定し、sed で一括削除・置換する手順を説明します。
なぜ見えない文字が設定ファイルに紛れ込むのか
これらの文字は多くの場合、コピー&ペーストをきっかけに混入します。主な経路として次のものが挙げられます。
- Web ページの内容をそのままコピーした(ノーブレークスペースが混入しやすい)
- Excel・Word で書いた内容を貼り付けた(全角スペースが混入しやすい)
- チャットツールやメーラーからコピーした(ゼロ幅文字が混入しやすい)
- 日本語入力モードのままスペースキーを押した(全角スペースが直接入力される)
通常の表示では半角スペースや空欄に見えるため、手作業での発見が難しく、設定ファイルのパースエラーや予期しない挙動の原因として見落とされがちです。
この記事で扱う文字の種類
BOM・改行コード・制御文字は扱いが異なるため、ここでは次の3種類に絞って説明します。
- 全角スペース(U+3000):日本語入力モードでスペースキーを押したときに入力される空白文字。半角スペースと見た目が非常に似ているため混入に気づきにくい。
- ノーブレークスペース(U+00A0):Web ページで改行させないために使われる特殊な空白文字。ブラウザからのコピペで混入しやすい。
- ゼロ幅文字(U+200B・U+FEFF など):文字と文字のあいだに挿入される幅ゼロの不可視文字。ゼロ幅スペース(U+200B)とゼロ幅ノーブレークスペース(U+FEFF)が代表的。
grep で混入箇所を特定する
まず grep を使って、対象ファイルのどの行に問題の文字が含まれているかを確認します。-P オプションで Perl 互換の正規表現を有効にし、-n で行番号を表示します。
全角スペースを検索する場合:
grep -Pn '\x{3000}' /etc/nginx/nginx.conf
ノーブレークスペースを検索する場合:
grep -Pn '\x{a0}' /etc/nginx/nginx.conf
ゼロ幅文字(U+200B と U+FEFF)を検索する場合:
grep -Pn '[\x{200b}\x{feff}]' /etc/nginx/nginx.conf
3種類をまとめて一度に検索するには、文字クラスにすべて列挙します:
grep -Pn '[\x{3000}\x{a0}\x{200b}\x{feff}]' /etc/nginx/nginx.conf
ディレクトリ配下のファイルをまとめて確認したい場合は -r を追加します:
grep -Prn '[\x{3000}\x{a0}\x{200b}\x{feff}]' /etc/nginx/
行番号と該当行が出力されれば、その行に不可視文字が含まれています。出力が何もなければ、対象ファイルには該当文字が存在しません。
sed で削除・置換する
混入箇所が特定できたら、sed を使って一括処理します。UTF-8 エンコーディングでの各文字のバイト列を指定して置換します。
全角スペースを半角スペースに置換する
全角スペース(U+3000)の UTF-8 表現は \xe3\x80\x80 の3バイトです:
sed -i 's/\xe3\x80\x80/ /g' /etc/nginx/nginx.conf
ノーブレークスペースを半角スペースに置換する
ノーブレークスペース(U+00A0)の UTF-8 表現は \xc2\xa0 の2バイトです:
sed -i 's/\xc2\xa0/ /g' /etc/nginx/nginx.conf
ゼロ幅文字を削除する
ゼロ幅文字は半角スペースへの置き換えではなく、完全に削除します。ゼロ幅スペース(U+200B)の UTF-8 表現は \xe2\x80\x8b です:
sed -i 's/\xe2\x80\x8b//g' /etc/nginx/nginx.conf
ゼロ幅ノーブレークスペース(U+FEFF)の UTF-8 表現は \xef\xbb\xbf です:
sed -i 's/\xef\xbb\xbf//g' /etc/nginx/nginx.conf
複数の文字をまとめて処理する
複数の文字を一度に処理したい場合は、-e オプションを組み合わせます:
sed -i \
-e 's/\xe3\x80\x80/ /g' \
-e 's/\xc2\xa0/ /g' \
-e 's/\xe2\x80\x8b//g' \
-e 's/\xef\xbb\xbf//g' \
/etc/nginx/nginx.conf
処理後の確認方法
sed を実行したあと、同じ grep コマンドで再検索して出力が0件になっていることを確認できます:
grep -Pn '[\x{3000}\x{a0}\x{200b}\x{feff}]' /etc/nginx/nginx.conf
echo $?
終了コードが 1(マッチなし)であれば、対象文字は除去されています。0 が返る場合はまだ残っているため、出力された行番号を手がかりに再確認してください。
nginx や Apache など設定ファイルを読み込むサービスであれば、文法チェックも合わせて行います:
nginx -t
よくあるつまずき
grep -P が使えないと言われる
一部の最小構成環境や Alpine Linux では、grep が -P(PCRE)に対応していない場合があります。代替手段として Python を使う方法があります:
python3 -I -c "
import sys
targets = ['\u3000', '\u00a0', '\u200b', '\ufeff']
with open(sys.argv[1], encoding='utf-8') as f:
for i, line in enumerate(f, 1):
if any(c in line for c in targets):
print(i, repr(line))
" /etc/nginx/nginx.conf
sed で文字化けする
ロケールが ASCII に設定されている環境では、マルチバイト文字の処理に失敗することがあります。コマンドの先頭に LANG=C.UTF-8 を付けると回避できることがあります:
LANG=C.UTF-8 sed -i 's/\xe3\x80\x80/ /g' /etc/nginx/nginx.conf
macOS と Linux で sed の動作が異なる
macOS の sed は BSD 系のため、-i の書き方が -i '' と異なります。本記事のコマンドは GNU sed(Linux 標準)を前提としています。macOS 上で作業する場合は Homebrew の gnu-sed をインストールし、gsed として使うと同じ構文が利用できます。
「コマンドは打てる。次は”現場で通用する型”を最短で身につけたい」——そんなあなたへ。
ネットの断片的なTipsをコピペするだけでは、体系的な運用スキルはなかなか積み上がりません。リナックスマスター.JPの無料メルマガ「リナマガ」では、現場で実際に使うLinuxサーバー運用の考え方を、順を追って実務目線でお届けしています。いま登録された方には、安全なサーバー構築の「型」をまとめた『Linuxサーバー構築入門マニュアル(図解60P)』を完全無料でプレゼント中です。
>> 図解60P『Linux入門マニュアル』を無料で受け取る
(メルマガ登録は10秒・いつでも解除OK)
※ 「独学の時間がもったいない」「プロから現場の技術を最短で学びたい」という本気の方には、2日で実務レベルが身につく初心者向けハンズオンセミナーもご用意しています。
