切り捨て文字を使用した bash 引数の作成

切り捨て文字を使用した bash 引数の作成

\u2263両側に2つのスペースで区切られたUnicode文字を使用して、bash関数の最初の2つの引数を印刷したいと思います。問題は、最終的なUnicodeを70列に表示する必要があることです。文字範囲が列68に$1達すると、$2追加の文字が切り捨てられます。

         1         2         3   V     4         5         6         7
1234567890123456789012345678901234567890123456789012345678901234567890

 U  FIRST-ARG                                            SECOND-ARG  U
 U  FIRST-ARG-LONGGGGGGGGGGGGGGGG                        SECOND-ARG  U

可能な最大幅で列番号(34文字で説明されている選択など)を指定できます。VFIRST-ARG

開始されたcl合計の最大長cr

local cl=34 cr=30
printf ' \u2263  %.${cl}s   %.${cr}s  \u2263\n' "$1" "$2"

答え1

は空白で埋められ、63に切り捨てられますbashprintf%-63.63sバイト文字ではないため、すべての文字がシングルバイトでない限り、書式設定/並べ替えには使用できません。 99.99%の文字は、複数のバイトを使用してUTF-8でエンコードされています。 U + 2263文字はUTF-8の場合は3バイト、GB18030の場合は4バイトでエンコードされています。

ksh93と同様に、bash${var:offset:length}は文字レベルでコピーされますが、すべての文字が単一幅の場合にのみ機能します。

テキストを正しく整列させるには、次のような方法があります。

  1. 文字の表示幅を考慮したパディング/切り捨て演算子を使用してください。
  2. 出力が端末に到達すると仮定し、制御シーケンスを使用して書き込み位置に目的のものを書き込み、そうでないものを削除するように端末に指示します。

1の場合、bashの代わりに組み込み演算子(ksh93やzshなど)を持つシェルを使用できます。

zshから:

align() printf ' \u2263  %s  \u2263\n' ${(j[  ]mr[63])@}

引数r[length]拡張フラグ(ここでは空白r[length][ ]がデフォルトのパディング文字に省略されています)rightは指定された長さで埋められ、m表示幅の単位の長さとともに使用されます。

または、後述のように、左揃え(および右パディング)と右揃え$1です。$2

align() printf ' \u2263  %s  \u2263\n' "${(mr[31])1} ${(ml[31])2}"

これを使用すると、ksh93より簡単になります。

align() printf ' \u2263  %-63.63Ls  \u2263\n' "$1  $2"

%Lsこれとは対照的に、バイトでは%sなく文字列を使用して、表示幅に応じて文字列を埋め、切り取ります。

または左$1と右を揃えます$2

align() printf ' \u2263  %-31.31Ls %31.31Ls  \u2263\n' "$1" "$2"

入力に制御文字が含まれていると機能しません。

2の場合は、自動マージンを無効にして全文を書き、68列に移動して" ≣"残りを書き込んで消去できます。

am_off=$(tput rmam) am_on=$(tput smam)
col68=$(tput cr; tput cuf 68)
del_to_eol=$(tput el)
align() {
  printf ' \u2263  %s\u2263%s\n' "$am_off$1  $2$col68  " "$del_to_eol$am_on"
}

答え2

2つの長いパラメータを取得します。

set -- '123456789.123456789.123456789.123456789.' '987654321.987654321.987654321.987654321.'

Vを40に設定すると、field1には40文字、field2には68-40 = 28文字があります。

cl=40
cr=$((68-cl))

今、私たちは最初のフィールドを左揃えし、2番目のフィールドを右揃えで印刷しようとします(長い引数では見えませんが)。 printf形式の文字列でフィールドの幅を設定するだけでは不十分で、パラメータの部分文字列のみを取得する必要があります。

printf '\u2263  %-*s%*s  \u2263\n' "$cl" "${1:0:cl}" "$cr" "${2:0:cr}"
≣  123456789.123456789.123456789.123456789.987654321.987654321.98765432  ≣

私たちはそれを見ることができます

  • "123456789.123456789.123456789.123456789."、最初のパラメーターの最初の40文字
  • "987654321.987654321.98765432"、2番目の最初の28文字です。

答え3

ああ?何が必要ですか?

問題が文字列の長さを操作する方法である場合は、ここで説明されている文字列関数を使用できます。 https://www.gnu.org/savannah-checkouts/gnu/bash/manual/bash.html#Shell-Parameter-Expansion

フォーマットされた方法で何かを印刷する必要がある場合は、Cとまったく同じフォーマットをprintf使用echoしてください。printf()https://www.gnu.org/savannah-checkouts/gnu/bash/manual/bash.html#index-printf

関連情報