区切り文字や範囲を指定して文字列を切り取る方法
ここでは区切り文字や範囲を指定して、文字列を切り取る方法について説明します。
といっても、何のことか分かりにくいと思うので、実例を示します。
まずは、次のような CSV ファイル a.csv があったとします。
$ cat a.csv 1,2,3,4,5 aaa,bbb,ccc,ddd,eee
cat コマンドはファイルの内容を標準出力に出力します。複数のファイルを指定すればファイルの内容がつながれて出力されることになります。
区切り文字を指定する場合
ここで、カンマで区切られた部分の 1 番目と 3 番目と 4 番目の区切り部分だけ抜き出すにはどうしたら良いでしょうか。
こうした目的には cut コマンドが使えます。
$ cut -d, -f1,3,4 a.csv 1,3,4 aaa,ccc,ddd
オプション -d, で区切り文字を指定します。ここではカンマ , を指定しています。
オプション -f で切り出す範囲を指定します。ここでは 1 番目、3 番目、4 番目を切り出したいので、-f1,3,4 を指定しています。
ちなみに、3 番目、4番目のように続いている部分はハイフンを使って、-f1,3-4 という風に範囲指定で書くこともできます。
ここではカンマ , をハイフン - に変えるだけなので、入力する文字数が減ったわけでもなく、有難みはありませんが、1番目の区切りから100番目の区切り、というときには範囲指定できるのはありがたいはずです。
縦を揃えて表示するには、column コマンドと組み合わせると良いです。
$ cut -d, -f1,3,4 a.csv | column -s, -t 1 3 4 aaa ccc ddd
column コマンドでは、-t で表組みを指定して、-s, で区切り文字をカンマ , に指定しています。
バイト数を指定する場合
次に同じく上記 a.csv を例にして、それぞれの行で先頭の 3 バイト毎に表示する方法です。
これも cut コマンドが使えます。
$ cut -b1-3 a.csv 1,2 aaa
-b1-3 オプションにて、切り取るバイト範囲を指定しています。
ここでは 1 バイト目から 3 バイト目までを、ハイフン - で範囲指定して切り出しています。
ここで注意しないといけないのは、文字数ではなく切り出すバイトを指定しているということです。
つまり、例えばエンコーディングが UTF-8 のファイルなどで日本語などのマルチバイト文字が混ざっている場合には、 下手すると文字が切れて文字化けする可能性がありますので注意が必要です。
$ cat z.csv あ,い,う,え,お a,b,c,d,e $ cut -b1-2 z.csv ?? a, $ cut -b1-3 z.csv あ a,b
文字化けたときに 16進数で内容をみると何が起きたのか、少しは分かる場合があります。次のように xxd コマンドで 16 進数表示すると・・・
$ cut -b1-2 z.csv | xxd 00000000: e381 0a61 2c0a ...a,.
となります。0x0A は改行文字なので、一行目はその前までの e381 であることがわかります。
HEX でみて E3 始まり、となれば、これは UTF-8 でエンコードされた日本語っぽいな、とわかる人も多いかもしれません。
というのは、ひらがなは Unicode での U+304x くらいのコードになりますが、これを UTF-8 エンコーディングすると、先頭バイトが E3 になるからです。
せっかくなので、実際に UTF8 エンコーディングを手動でやってみましょう。
ひらがなの「あ」は Unicode で U+3042 です。2進数で書くと 0011 0000 0100 0010 です。
UTF-8 のエンコーディングは U+0800 から U+FFFF に対しては、1110 xxxx 10xx xxxx 10xx xxxx の x を埋める形でのエンコードです。 先ほどの 「あ」の 2 進数で x を埋めていくと、次のように E3 81 82 となります。
U+3042 の 2進数 → 0011 0000 0100 0010 この範囲の UTF8 エンコーディングルール → 1110 xxxx 10xx xxxx 10xx xxxx よって、 1110 0011 1000 0001 1000 0010 → E 3 8 1 8 2
かなり脱線しましたが、知っておいて損はないです。
こういうことを知っておくと、文字化けした時に単に「ファイルが壊れた」の一言で終わらずに、なぜ、どういう理由で壊れたかわかるようになります。