文字列を特定の長さで埋めるために先行文字を追加するには?
文字列が20文字より短い場合は、文字列の前にゼロを追加したいとします。
printf '%020s\n' "$line"
しかし、これはゼロのような他の何もではなく先行スペースで文字列を埋めます。
文字列は、数字やその他の文字を含む任意の文字列です。
printf '%020i' $number
文字列をorの数字+残りに分割したくありませんprintf '%020d $number'
。
私の現在の出力は次のとおりです
shortstring
私が望む出力は次のとおりです。
000000000shortstring
答え1
手動で記入してください。 POSIXツールの使用にこだわったら、これよりも簡単な解決策はないと思います。
while [ ${#line} -lt 20 ]; do
line=0$line
done
または
n=${#line}
while [ $n -lt 20 ]; do
printf '0'
n=$((n-1))
done
printf "$line\n"
もちろん、zshには対応する構文があります。上記のコードスニペットとは異なり、このコードスニペットは、文字列が20文字を超えると文字列を切り捨てます。切り捨てたくない場合は、文字列の末尾を追加できます。
print -r ${(l:20::0:)line}
print -r ${(l:20::0:)line}${line:20}
答え2
@Gnoucがすでに指摘したように、すでに半分くらい来ました。
line='some chars'
printf '%0'$((20-${#line}))'d%s\n' 0 "$line"
###OUTPUT###
0000000000some chars
もちろん、行が20文字を超えてもまだゼロを取得します。もし printf
-
型文字列のダッシュを正しく処理できないため、エラーは発生しません。(これは明らかにより可能性の高いシナリオです)。しかし、これは扱いやすいです。
printf "%.$((((l=20-${#line})>0)*l))d%s\n" 0 "$line"
書式文字列はprintf
' を使用します。%.
正確%.0d
フラグは、示された長さに対して分数引数をゼロで埋めます。それ以外の場合は、null または null 精度の場合、先行するゼロを%.d
表示された数字に切り捨てます。このように:
printf '#%.0d%c%.5d' 0000000 ':separator' 4
#:00004
(注:この%c
形式は、関連する引数の最初の文字を印刷します)
算術$((
式は))
最初にvarを$l
20マイナスに設定し、それぞれ0より小さいか大きい場合は0または1と評価し、${#line}
最後にそれを掛けます。したがって、20-が0より小さい場合はこれを行い、0より大きい場合はこれを行います。$l
$l
${#line}
$((0*l))
$((1*l))
このようにしていつも20との差と同じ数の先行ゼロのみを印刷します${#line}
。このように:
line='some chars'
printf "#%.$((((l=20-${#line})>0)*l))d%s\n" 0 "$line"
#0000000000some chars
そして…
line='some chars'
printf "#%.$((((l=4-${#line})>0)*l))d%s\n" 0 "$line"
#some chars
あなたは同じものを使うことができます%.
正確フィールドタイプにも同様に適用されますs
。たとえば、次のようになります。
line='some chars'
printf "#%.$((((l=4-${#line})>0)*l))d%.4s\n" 0 "$line"
#some
...必要に応じて切り取ります。
以下はループです。以下は5回繰り返されます。
line=
until line=fivec$line; [ $((l)) -lt 0 ]
do printf "#%.$((((l=20-${#line})>0)*l))d%s\n" 0 "$line"
done
#000000000000000fivec
#0000000000fivecfivec
#00000fivecfivecfivec
#fivecfivecfivecfivec
#fivecfivecfivecfivecfivec
表示されたゼロはシェル変数の値にまったく含まれておらず(もちろん)、$line
フォーマット文字列が指示するように自動的に生成されることに注意する価値があります。printf
より正確な同じループは次のとおりです%.20s
。
line=
until line=fivec$line; [ $((l)) -lt 0 ]
do printf "#%.$((((l=20-${#line})>0)*l))d%.20s\n" 0 "$line"
done
#000000000000000fivec
#0000000000fivecfivec
#00000fivecfivecfivec
#fivecfivecfivecfivec
#fivecfivecfivecfivec
それでできるもう一つのことは本当に面白いです。printf
ゼロを動的に生成する機能を組み合わせることで、必要なだけ$IFS
文字列を使用できます。たとえば、次のようになります。
IFS=0 ; printf '10 lines\n%s' $(printf %010d) ; unset IFS
###OUTPUT###
10 lines
10 lines
10 lines
10 lines
10 lines
10 lines
10 lines
10 lines
10 lines
10 lines
答え3
%s
文字列形式の仕様です。ゼロパディングのみデジタル変換のために存在すると定義されています:
0d、i、o、u、x、 。他の変換の場合、動作は定義されません。
$line
数値の場合は、次を使用します。
printf '%020i\n' $line
必要な結果(または他の数値書式指定子の1つ)を取得するには、値がより複雑ですが、数値で始まる場合は次のようになります。
printf '%020i %s\n' $num $restofline
数字と文字列を一度に組み合わせてみてください。
答え4
利用可能な場合perl
:
$ perl -e 'print sprintf "%020s\n","shortstring"'
000000000shortstring
より一般的な場合:
$ perl -e 'print sprintf "%020s\n",shift' shortstring
000000000shortstring
$ perl -e 'print sprintf "%020s\n", $_ for @ARGV' shortstring qwerty
000000000shortstring
00000000000000qwerty
ノート
一部のプラットフォームでは、少なくともをAIX
使用するときは0を前に出力文字列を書式設定でき、GNU gcc
コンパイル時に警告が表示されます。
$ cat test.c
#include <stdio.h>
int main() {
printf("%08s\n", "qwerty");
return 0;
}
それから:
$ gcc -Wall test.c
test.c: In function ‘main’:
test.c:4:5: warning: '0' flag used with ‘%s’ gnu_printf format [-Wformat]
これを使用したくない場合は、次をperl
試してください。
$ line=shortstring
$ printf "%0$((20-${#line}))d%s" 0 $line
000000000shortstring
文字列の長さが20より大きい場合、このメソッドはそれを処理できません。 @mikeserv応答を使用して問題を処理したり、以前に確認したりするために使用できますprintf
。