端末からUnicodeシンボルを削除する方法は?

端末からUnicodeシンボルを削除する方法は?

一部の記号は2文字単位を占めています。次のスクリプトを考えてみましょう。

#!/usr/bin/env bash
echo '银^Htest'
echo 'а^Htest'

出力:

 test
test

電子記号のコードポイントをどうやって知ることができますか?一種の正規表現ですか?文字列が占める文字単位の数を計算するには?出力からすべてをどのように削除できますか?

それが重要であれば私はxterm

UPDより大きな画像を表示するために進捗状況を表示し、いくつかの情報を出力、消去、再出力しようとします。これを行うには、カーソルを行の先頭(\r)に移動し、空白のある行を削除します(tput cols)、次にカーソルを移動します(\r)。しかし、この出力は複数行にまたがることができることがわかりました。そのため、文字数を数えて後ろに移動(^H)して消去し(文字列の長さだけ空白を出力)、再び後ろに移動()することにしました^H

ベストアンサー1

これは実際には4つの質問です。

  1. コードポイントをどうやって知ることができますか?
  2. 一種の正規表現ですか?
  3. 文字列が占める文字単位の数を計算するには?
  4. 出力からすべてをどのように削除できますか?

OPではxtermに言及しましたが、最後の2つだけがxtermに固有のものです。

(1)と(2)の場合、echoコマンドはあまり役に立ちません。使えばいいと思います。printf、バックスラッシュエスケープを認識します。いくつかの実装では(例:GNUコアツール)(Unicode定数を含む)

printf '\u94f6\btest'

たとえ一般的な表現、Perl(UTF-8を扱うことができます)などのスクリプト言語を使用することをお勧めします。

追加資料:

質問(3)と(4)がもっと面白いです。まず、スクリプトは文字列に必要な文字単位の数を事前に知ることができず、事実後にのみ測定できます。これは、幅が端末とカーネルの動作の組み合わせに基づいているためです。

  • xtermの使用文字の幅を決定するには、「ワイド」(デュアル幅)フォントにいくつかの問題があり、wcwidthの実装はあいまいな幅のUnicode値に対する開発者の偏見を反映しています。 Markus Kuhnのコピーを使用するようにxtermを(実行時に)設定できます。実装するwcwidth;実際のシステムロケール情報が完全でなく一致しない可能性があります。
  • xterm が 2 バイト文字の一部を消去するよう指示すると (与えられた例のように) 他の部分を空白で置き換えます。 xtermを模倣する他のほとんどの端末はこれを行います(迅速な検査により、1つの端末が単にカーソルを動かして広い文字とASCIIテキストが重なることを発見しました)。もしあなたなら知る値は倍幅で、カーソルがある位置の概念を簡単に調整できます。
  • それ以降のLinuxカーネルとwcwidthLinuxベースのシステム2004年stty次の機能がありますiutf8

標準入力モードで正しい編集サポートを提供するために、入力がUTF-8でエンコードされたことをカーネルに通知します。

  • 編集に役立つLinuxカーネル機能入力するこれは、バックスペースキーが古い文字を削除したときにターミナルドライバが合理的な操作を実行するのに役立ちます。しかし、比較する機能はありません。出力

あなたできる、推奨されるようにカーソル位置の報告(エスケープシーケンス)を使用して、さまざまな点でカーソル位置を見つけます。しかし、それを使って線を消去する方法を決定すると、もっと簡単に見えます。移動するUnicode値を印刷する前の位置に移動し、その点から削除します。

あるいは、ワイド文字を印刷する前にカーソル位置を保存してから復元(戻る)するように端末に指示することもできます。これはよりクリーンで予測可能に見えるかもしれません。カーソル位置が復元されると、その行を消去できます。どちらもエスケープシーケンスを使用して実行できます。tput:

tput sc
printf '\u94f6'
tput rc
tput el
printf 'test'

デモに加えて、端末に保存されているカーソル位置が1つだけで、単一/二重幅文字が消去されるように行全体が消去されるという欠点があります。しかし、カーソルは最終的に「正しい」位置に達します。

おすすめ記事