LoginSignup
0
0

multibyte cut

Last updated at Posted at 2024-05-28

困ったこと

マルチバイト文字を単純にcutしようとすると、文字の途中のバイトで切れてしまう。

### ひらがなは3バイト
$ printf あ | wc -c
3

$ printf あいうえお | wc -c
15

### 先頭4バイトを表示 -> `い`が途中のバイトで切れる
$ printf あい | cut -b-4
あ�

以下に解決方法を示す。
なお、普通の日本語の文章なら動作すると思うが、サロゲートペアとかで正しく動くかは不明。

先頭の3文字を抽出

$ printf aあbいcうdえeお | grep -o '^.\{,3\}'
aあb

$ printf aあbいcうdえeお | awk -F '' '{print $1$2$3}'
aあb

一旦UTF-32等の固定長の文字コードに変換した後に切り出す方法もあるが、シェルスクリプトで実現するのは難しそう。

日本語2文字幅、ASCII 1文字幅としてカウントする

### 3文字幅抽出
$ printf 'aあbいcうdえeお' | awk -F '' '{for(i=1;i<=NF;i++){w+=2**($i!~/[\x00-\x7f]/);if(w>WIDTH){break}printf $i}}{printf "\n";w=0}' WIDTH=3
aあ

### 4文字幅抽出
$ printf 'aあbいcうdえeお' | awk -F '' '{for(i=1;i<=NF;i++){w+=2**($i!~/[\x00-\x7f]/);if(w>WIDTH){break}printf $i}}{printf "\n";w=0}' WIDTH=4
aあb

### 5文字幅抽出 (`い`を入れると6文字幅なので`い`はカット)
$ printf 'aあbいcうdえeお' | awk -F '' '{for(i=1;i<=NF;i++){w+=2**($i!~/[\x00-\x7f]/);if(w>WIDTH){break}printf $i}}{printf "\n";w=0}' WIDTH=5
aあb

### 6文字幅抽出
$ printf 'aあbいcうdえeお' | awk -F '' '{for(i=1;i<=NF;i++){w+=2**($i!~/[\x00-\x7f]/);if(w>WIDTH){break}printf $i}}{printf "\n";w=0}' WIDTH=6
aあbい
0
0
0

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
0
0