UTF-8で `cut -c`(`--characters`)を使用できませんか?

UTF-8で `cut -c`(`--characters`)を使用できませんか?

このコマンドには、オプションを使用してバイトではなく文字を処理するcutオプションがあります。しかし、これはロケールでは機能しないようです。-c-ben_US.UTF-8

2番目のバイトは2番目のASCII文字を提供します(UTF-8と同じ方法でエンコードされています)。

$ printf 'ABC' | cut -b 2          
B

ただし、UTF-8ロケールの3つのギリシャ語の非ASCII文字のうち、2番目の文字は提供されていません。

$ printf 'αβγ' | cut -b 2         

大丈夫、今回は2回目です。バイト
それでは、2番目のものを見ますか?特徴代わりに:

$ printf 'αβγ' | cut -c 2 

壊れたようですね。
いくつかの実験の後、範囲に3-42番目の文字が表示されることがわかりました。

$ printf 'αβγ' | cut -c 3-4
β

ただし、これはバイト3〜4と同じです。

$ printf 'αβγ' | cut -b 3-4
β

したがって、UTF-8よりも重要では-cありません。-b

私はこのロケールがUTF-8には適していないと予想しましたが、比較すると、オプション()を使用してバイトを計算するためによく使用されるように動作しますwc(混乱したオプション名に注意してください。)
-c--bytes

$ printf 'αβγ' | wc -c
6

-mただし、オプション(--chars)を使用して文字数を数えることもできるので、次のように動作します。

$ printf 'αβγ' | wc -m
3

だから私の構成は大丈夫に見えますが、何か特別なものがありますcut

たぶんUTF-8をまったくサポートしていませんか?しかし、マルチバイト文字をサポートしているようです。それ以外の場合と-bサポートする必要はありません-c

それでは、何が間違っていますか?なぜ?


私が知っている限り、ロケールはutf8に適しているようです。

$ locale
LANG=en_US.UTF-8
LANGUAGE=en_US
LC_CTYPE=en_US.UTF-8
LC_NUMERIC="en_US.UTF-8"
LC_TIME="en_US.UTF-8"
LC_COLLATE="en_US.UTF-8"
LC_MONETARY="en_US.UTF-8"
LC_MESSAGES="en_US.UTF-8"
LC_PAPER="en_US.UTF-8"
LC_NAME="en_US.UTF-8"
LC_ADDRESS="en_US.UTF-8"
LC_TELEPHONE="en_US.UTF-8"
LC_MEASUREMENT="en_US.UTF-8"
LC_IDENTIFICATION="en_US.UTF-8"
LC_ALL=

入力(バイト単位):

$ printf 'αβγ' | hd 
00000000  ce b1 ce b2 ce b3                                 |......|
00000006

答え1

あなたはどのようなものを使用しているのか言っていませんが、cutGNUの長いオプションについて言及したので、--characters私はそれがそのオプションだと思います。このような場合は注意してください段落の内容info coreutils 'cut invocation':

‘-c character-list’
‘--characters=character-list’

文字リストに記載されている場所の文字のみを印刷する場合に選択します。-b今と同じしかし、国際化によって状況が変わります。

(強調追加)

現在、GNUはcut常にシングルバイトの「文字」側で動作するため、予想される動作が表示されます。


サポート-b-cオプションの両方POSIXの要件cut- マルチバイトをサポートし、正しく機能するため、GNUに追加されていませんが、POSIX準拠の入力でエラーを防ぐためです。-c他の実装でも同じことが行われますcutFreeBSD'砂オペレーティングシステム少なくともそうです。

これは歴史的行動-c-b新しい追加は、-cマルチバイト文字を処理できるようにバイトロールに代わるものです。おそらく、数年後には常に期待どおりに機能します。もちろん進行速度がそれほど速くはありませんが(10年を超えました)。牛に似た一種の栄養cut -nオプションは実装されていません。しかし、直交して変換を支援するように設計されています。原因が何であるかはわかりませんが、以前のスクリプトには潜在的な互換性の問題があり、問題になる可能性があります。

答え2

colrmutil-linux(ほとんどのディストリビューションにすでにインストールされているものの一部)は、国際化をよりよく処理するようです。

$ echo 'αβγ' | colrm 3
αβ
$ echo 'αβγ' | colrm 2
α

番号付けに注意してください。印刷された文字までcolrm N列が削除されます。NN-1

クレジット取引)

答え3

多くの実装はマルチバイトを認識するので、これをgrep使用して 。grep -ocut -c

最初の2文字:

$ echo Τηεοδ29 | grep -o '^..'
Τη

最後の3文字:

$ echo Τηεοδ29 | grep -o '...$'
δ29

2番目の文字:

$ echo Τηεοδ29 | grep -o '^..' | grep -o '.$'
η

期間数を調整するか、{x,y}構文を使用して範囲をシミュレートしますcut

答え4

8年以上にわたってOPの問題を再現することはできません(MacOS 13.4 Ventura)。

~$ printf 'ABC' | cut -b 2
B
~$ printf 'αβγ' | cut -b 2
~$ printf 'αβγ' | cut -c 2
β
~$ printf 'αβγ' | cut -c 3-4
γ
~$ printf 'αβγ' | cut -b 3-4
β
~$ printf 'αβγ' | wc -c
       6
~$ printf 'αβγ' | wc -m
       3 

上記の内容がOPが望む答えだと思いますか?行の終わりはcut -c 3-4実際にγ%下に返され、部分行zsh(返される可能性があるよりも多くの文字が要求されます)を示します。

-$ man cut仕様の拡張として、macOS 13.4 August 3, 2017追加フラグ付きのIEEE Std 1003.2-1992(「POSIX.2」)以外のバージョンは提供されていません。-w"歴史:cutコマンドはAT&T System III UNIXに表示されます。"

関連情報