テキストから必要な部分を抜き出すcutコマンドです。cutコマンドは特定範囲の文字を抜き出せます。文字列の中から任意の場所の文字を1文字単位で抜き出すこともできます。また、csv形式やタブ区切りテキストで必要な列だけを抜き出す事もできます。
1文字だけ抜き出す(英数字)
まず、テキストファイル内から指定した文字数だけ抜き出してみましょう。cutはパイプからの文字列を利用できるので、まずechoと組み合わせてテストしてみます。
echoで出力した文字列の最初の1文字を抜き出してみます。1文字抜き出すにはオプションのcを指定し、その直後に抜き出す文字の位置を指定します。以下のようにすると文字列ABCDEFの最初の文字であるAが抜き出されます。なお、文字の位置は最初が1で次の文字が2、その次が3といった順番で1ずつ増えていきます。いくつかのプログラミング言語で見られる最初の文字の位置が0というわけではありません。
echo ABCDEF | cut -c 1
2番目の文字を抜き出す場合は以下のようになります。4番目ならcut -c 4のように指定するだけです。
echo ABCDEF | cut -c 2
echo ABCDEF | cut -c 4
1文字抜き出す場合、英数字では問題は発生しません。元々1バイトで表現できる英数字(および主な記号。ASCIIコード範囲)なら安心して使うことができます。UNIXが登場した時点では日本語表示はもちろん、マルチバイト文字が存在していないからです。
日本語を1文字だけ抜き出す前に
次に日本語を1文字だけ抜き出してみましょう。と書くのは簡単ですが、日本語というかマルチバイト文字に関しては、なかなか面倒な事情があります。というのも日本語を示すための方法(文字コード)が複数あるためです。文字コードについて説明すると大変面倒なことになるので、ここでは大まかな、かなりざっくりとした説明に留めておきます。なお、Unicodeを使った文字に関しては以前の連載を参照してください。
・第78回 echoコマンドで絵文字などを表示する
https://news.mynavi.jp/techplus/article/natonakucommand-78/
2000年あたりまではUnicodeを含め様々な文字コードがありました。特に英数字ではない漢字などでは1つの漢字を表すのに2バイト以上を必要としました。漢字IN,漢字OUTなど、ここから漢字を示すコードですよみたいなコードであったり、より少ないバイト数で文字を示すために工夫されたShift JISなどがありました。また、UNIXではEUC (Extend UNIX Code) が利用されていました。
・漢字IN,漢字OUT
https://ja.wikipedia.org/wiki/%E6%BC%A2%E5%AD%97%E3%82%B7%E3%83%95%E3%83%88%E3%82%B3%E3%83%BC%E3%83%89
・文字コード
https://ja.wikipedia.org/wiki/%E6%96%87%E5%AD%97%E3%82%B3%E3%83%BC%E3%83%89
日本ではShift JISが多く利用されてきたため、今でも多くのテキストデータがShift JISになっている場合があります。そのような場合はNKFなど文字コードを変換するツールを利用してUnicodeにしておくのがよいでしょう。ただし、Unicodeなら全ての文字を内包しているわけではありませんので注意が必要です。特に人名(外字等で定義されたものも含む)や変体仮名、機種依存文字など固有の文字に関しては含まれていないことがあります。また、1980年代のコンピューターの場合、多種多様な機種があり、それらで使用されていた文字は含まれていないことがあります。(Unicode 16で一部の古い機種の文字は含まれるようになりました)
現時点ではUnicodeで全て解決とはいきませんが、最も多く利用されている状況でもあります。以後の説明では日本語を含むテキストはUnicode (UTF-8) であるとします。また、UTF-8でもBOM (Byte Order Mark) は付いていないものとします。なお、Unicodeに対応していない環境では動きませんので注意してください。
なお、Raspberry Pi 5およびUbuntu 24.04では日本語処理がうまくできなかった感じなので以後の日本語処理部分はmacOSのみの実行結果になっています。(私が使用しているOSの設定が駄目でうまく処理できていない可能性もあります)
1文字だけ抜き出す(日本語)
それでは前提条件が整ったところで日本語1文字抜き出してみましょう。といっても指定できるオプションなどは英文字の場合と変わりません。以下のようにすると先頭の1文字である「春」の文字が抜き出されます。
echo '春はあけぼの' | cut -c 1
2文字目であれば以下のようになります。
echo '春はあけぼの' | cut -c 2
cutコマンドでは文字数を超える抜き出す位置を指定した場合でもエラーは発生しません。ただし、macOSの一部のバージョンと環境では文字数を大きな値にした場合、メモリ不足で実行できないことがあります。(強制終了するかどうかのダイアログが出ます)
echo '春はあけぼの' | cut -c 9
以下はおまけですが次のようにシェルスクリプトを作ると文字を1文字ずつ抜き出して出力してくれます。
#!/bin/bash
for i in {1..6} ; do
echo '春はあけぼの' | cut -c ${i}
done
範囲を指定して文字を抜き出す
次に範囲を指定して文字を抜き出してみましょう。2番目から5番目の文字を抜き出すには以下のように-cの後に2-5といった範囲を指定します。
echo 'ABCDEFGHIJKMNOP' | cut -c 2-5
文字列を指定した位置から最後まで抜き出す場合は以下のように指定します。抜き出す位置の後に-を指定するだけです。
echo 'ABCDEFGHIJKMNOP' | cut -c 2-
最初の文字から指定した位置までの文字を抜き出す場合は-の後に抜き出す最後の文字の位置を指定します。
echo 'ABCDEFGHIJKMNOP' | cut -c -5
ちなみに抜き出した文字を保存したい場合はリダイレクト(>)を使います。以下のようにするとカレントディレクトリにmoji.txtというファイル名で保存されます。
echo 'ABCDEFGHIJKMNOP' | cut -c 2-5 > moji.txt
不連続な文字範囲の指定
cutコマンドは特定の位置や範囲だけでなく,で区切って不連続な指定もできます。 以下のようにすると1,3,5,7の位置にある文字が抜き出されます。
echo 'ABCDEFGHIJKMNOP' | cut -c 1,3,5,7
範囲指定と組み合わせることもできます。
echo 'ABCDEFGHIJKMNOP' | cut -c 2-5,7
さらに組み合わせることで複雑な文字位置を指定して抜き出すこともできます。
echo 'ABCDEFGHIJKMNOP' | cut -c 2-5,7,9-11
echo 'ABCDEFGHIJKMNOP' | cut -c 2-5,7,9-11,14-