現在のコードは次のとおりです。x=${y:0:40}
文字列の長さを40文字に制限します。文字列が40文字未満の場合は、末尾の位置をスペースで埋めることはできますか?
もしそうならy="very short text"
私は私がy
次のようにしたいと思います:
y="非常に短いテキスト(+25個の末尾のスペース)」
答え1
あなたは試す必要がありますprintf
:
printf '%-40s' "$y"
答え2
これらの文字がすべてシングルバイトの場合、つまりロケールの文字セットがシングルバイト(iso8859-1など)、またはロケールの文字セットはUTF-8ですが、テキストはASCII専用の場合は次のようになります。
printf -v y %-40.40s "$y"
これには切り捨てとパディングが含まれます。
そうでない場合は、いつでも40個のスペースを追加して必要な方法を使用できます${y:0:40}
。
printf -v pad %40s
y=$y$pad
y=${y:0:40}
zsh
専用の左右のパディング演算子があります。
y=${(r:40:)y}
(切断も行われます)。zsh
数printf
はバイトではなく文字単位(またはパラメータ拡張フラグも使用されている場合は文字単位の表示幅に基づいているm
)なので、bash
上記の問題は発生しません。ただし、zsh
このオプションを使用するにはバージョン5.3以降が必要です-v
。
また、見ることができますこの関連質問への回答文字の幅が異なる場合は、詳細をご覧ください。
答え3
純粋なbash
:
ten=" "
forty="$ten$ten$ten$ten"
y="very short text"
y="${y:0:40}${forty:0:$((40 - ${#y}))}"
echo "'${y}'"
方法は、各文字列を切り取り、0〜40のスペースを追加することです。
出力(一重引用符の位置を参照):
'very short text '
答え4
一般的な使用アドバイスはprintf
間違っています。文字以外のバイトを計算します。文字を正しく計算しても(ほとんどの場合)、
配列を持つシェルにのみ使用が制限されます。${var:start:length}
より良い計算方法は、${#var}
計算する必要がある文字によって決まります。
$ for var in 1 123 ΐΐΐ ᾂᾂ "㉑㉒㉓" aáéí;
> do
> printf '|%s%*s|\n' "$var" "$((10-${#var}))" "";
> done
|1 |
|123 |
|ΐΐΐ |
|ᾂᾂ |
|㉑㉒㉓ |
|aáéí |
しかし、文字列の長さを切り捨てる唯一の移植可能な方法は、grepを使用することです。
#!/bin/sh
n=${1:-10}
for str in 1 123 123456789012 ΐ ΐΐΐ ΐΐΐΐΐΐΐΐΐΐ ΐΐΐΐΐΐΐΐΐΐΐΐΐΐΐΐΐΐΐΐ ᾂᾂᾂᾂᾂ "㉑㉒㉓㉔㉕㉖㉗㉘㉙㉚" aáéíóúüñm
do
str=$str$(printf '%*s' "$n" "") # pad with `n` spaces.
var=$(echo "${str}"|grep -Eo "^.{1,$n}") # limit length to `n`
printf '|%s|\n' "${var}"
done
以下を印刷します。
|1 |
|123 |
|1234567890|
|ΐ |
|ΐΐΐ |
|ΐΐΐΐΐΐΐΐΐΐ|
|ΐΐΐΐΐΐΐΐΐΐ|
|ᾂᾂᾂᾂᾂ |
|㉑㉒㉓㉔㉕㉖㉗㉘㉙㉚|
|aáéíóúüñm |
丸められた数字は幅が2倍です。それでも10文字がありますが、幅の2倍を占めます。これは一部のシェルで使用できますvar=${str:0:n}
。
印刷機能
printf の実装は通常 POSIX 仕様に従ってバイト計算に制限されます。 1文字あたり1バイトのASCII文字またはその他の文字には問題はありません。しかし、他のほとんどの国際人事はこうしています。$ printf '|%-10.9s|..\n' 1234567890 ΐ U+0390 ᾂ U+1F82 "㉑㉒㉓㉔㉕㉖㉗㉘㉙㉚" aáéíóúüñm
|123456789 |..
|ΐ |..
|U+0390 |..
|ᾂ |..
|U+1F82 |..
|㉑㉒㉓ |..
|aáéíó |..
printfは、次の形式で10文字のスペースに9文字を印刷する必要があります%10.9s
。それはまさにそうします1234567890
。数字を9から切り取り、10個のスペースに印刷します|123456789 |..
。ところで、ΐ
1桁で失敗し、ᾂ
2桁で失敗し、㉑㉒㉓
3桁で失敗し、最終的に4桁aáéíó
で失敗しました。
これには2つの異なる問題があります。
- 1 つ目は文字ごとに使用されるバイト数です。たとえば、
㉑
need3
は3文字を9バイトにします(printfに必要なもの)。この場合、printfは3文字を9バイトとして計算します。 - 2番目は各文字の幅です。これらのすべてには
áéíóúüñ
2バイトが必要で、1つの位置の幅(スペースと同じ幅)です。したがって、printf
印刷aáéíó
( の 1 バイトa
、残りの 2 バイトが 9 バイトを構成する)は文字 5 つに末尾の空白のみが含まれるため、総幅は 6 になります。つまり、スペース4つが不足しています。 - 各文字は印刷に3バイトが必要です
㉑㉒㉓
が、文字ごとに2つのスペースを使用するため、文字列を表示するときの幅は6つのスペースになります。