LoginSignup
13
14

More than 5 years have passed since last update.

bashでもUTF-8 with BOMなファイルを作りたい

Last updated at Posted at 2017-01-14

はじめに

普段はC++の記事を投稿しています。
Windows使いなもんで、Bashを使うのに

とかしてやってます(どんだけ間に挟むんだ)

動機

ちょっとcsvを自動加工する必要が出てきまして、Windows向けにpowershellとLinux向けにShellScript(on bash)を書くことになったんですね。

要件として、出力ファイルはUTF-8 with BOMにしたいというものがありまして、powershellだと

"arikitari" | out-file -encoding:utf8 $out_file
"na" | Add-Content -encoding:utf8 $out_file
"world!" | Add-Content -encoding:utf8 $out_file

とかすれば良かったりするんですが、はて、これはShellScript(on bash)ではどうすればいいのかな、と。

先行例

コマンドラインでUTF-8テキストのBOMを追加したり削除したりする – skmks

もちろんそういうことを思う人は私だけではないわけで、先行例がありました。
ここではnkfコマンドとuconvコマンドを使う2つの例が出ていました。
そして多分、nkfコマンドを使うのが王道なんでしょう。

問題点

image

nkfコマンドもuconvコマンドも普通(CentOS 7)入っていないんですね!

ではどうするか

解決の糸口となったのがこの記事です。

Bash/Zsh スクリプトならバイナリを扱える。さて何をしよう……
http://qiita.com/akinomyoga/items/215faa630508ffc6e6e0

どうやらbash/zshでならバイナリを扱えるというではないですか。
つまり

UTF-8のBOM
0xEF 0xBB 0xBF

を直接書き込めばいいわけです。

というわけで実装した

#!/bin/bash
function writebinary {
  LC_ALL=C printf "$(printf '\\x%x' "${data[@]}")" > "$1"
}
function write_utf8_bom {
  #BOM:0xEF 0xBB 0xBF
  local -a data=(239 187 191)
  writebinary $1
}
write_utf8_bom bom.txt
echo "arikitari" >> bom.txt
echo "na" >> bom.txt
echo "world!" >> bom.txt

確認してみましょう。

$hexdump -C bom.txt
00000000  ef bb bf 61 72 69 6b 69  74 61 72 69 0a 6e 61 0a  |...arikitari.na.|
00000010  77 6f 72 6c 64 21 0a                              |world!.|
00000017

いいですね。

追記

@kkdd さんから教えてもらったので。

まずechoコマンドのmanを覗いてみましょう。

ECHO(1)                                                                                                 User Commands                                                                                                ECHO(1)

NAME
       echo - display a line of text

SYNOPSIS
       echo [SHORT-OPTION]... [STRING]...
       echo LONG-OPTION

DESCRIPTION
       Echo the STRING(s) to standard output.

       -n     do not output the trailing newline

       -e     enable interpretation of backslash escapes

改行を阻止する-nとエスケープを使えるようにする-eを組み合わせると

#!/bin/bash
function f()
{
  echo -en '\xef\xbb\xbf'
  echo "arikiari"
  echo "na"
  echo "world!"
}
f > bom.txt
$hexdump -C bom.txt
00000000  ef bb bf 61 72 69 6b 69  61 72 69 0a 6e 61 0a 77  |...arikiari.na.w|
00000010  6f 72 6c 64 21 0a                                 |orld!.|
00000016

同じ結果が得られたゾイ!これはいい。教えていただきありがとうございます。

余談

ところでこれ、#!/bin/bash#!/bin/shにしても動くんですが、うーむ、わかんねぇ。

License

CC BY 4.0

CC-BY icon.svg

13
14
8

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
13
14