printfコマンドを使用して文字をN回書きます

printfコマンドを使用して文字をN回書きます

Linuxで文字を繰り返す次のコマンドが見つかりました。

printf 'H%.0s' {1..5000} > H.txt

たとえば、何度もH繰り返したいと思います。5000ここでは何を意味しますか%.0s

答え1

このコマンドは、シェルに従って5000個の引数を生成し、それをprintfシェルに渡して無視します。かなり高速で関連性があるように見えるかもしれませんが、シェルはまだすべての文字列をargsとして生成する必要があります。(そして定義)など。

シェルの最初の反復が5000に達するまで結果Hを印刷できないことに加えて、このコマンドは数値文字列引数を格納して区切るためにメモリを消費します。printf 追加するHs。あなたができるように:

printf %05000s|tr \  H

...5000 個の空白を含む文字列を生成します。少なくとも各スペースは通常1バイトに過ぎず、区別されないため、区分コストは必要ありません。一部のテストでは、この場合でも必要な分岐および配管コストはわずかtr5000バイトであってもそれほど価値があり、数値が高くなるほどほぼ常にそうです。

私は逃げた...

time bash -c 'printf H%.0s {1..5000}' >/dev/null

...そして...

time bash -c 'printf %05000s|tr \  H' >/dev/null

それぞれ5回程度(ここには科学的根拠はありません。ただの逸話だけです)支柱の拡張バージョンの平均総処理時間は0.02秒を少し超えましたが、このtrバージョンの平均総処理時間は約0.012秒で、そのtrバージョンは毎回それを超えました。驚くべきことは言えません。{brace expansion}これはインタラクティブシェルに便利な短縮機能ですが、一般的にあらゆる種類のスクリプトにはかなり無駄です。一般的な形態:

for i in {[num]..[num]}; do ...

...よく考えてみてください。本当にそうですね。二つ forLoop - 最初は内部的であり、すべてのイテレータを保存してループに対して再度繰り返す前に、シェルがこれらのイテレータを生成するために何らかの方法で繰り返す必要があることを意味しますfor。一般に、次のようなことを行う方が良いでしょう。

iterator=$start
until [ "$((iterator+=interval))" -gt "$end" ]; do ...

これは、非常に少ない値のみを保存し、繰り返し可能な項目を作成するときに繰り返し、使用時に上書きするためです。

とにかく、前述の空白の塗りつぶしと同様に、必要な数のprintf数字をゼロで埋めることもできます。たとえば、次のようになります。

printf %05000d

printf型文字列で指定された引数ごとに引数が見つからない場合は、空の文字列が使用されるため、引数なしで両方の操作を実行します。これは数値引数に対してゼロまたは文字として解釈されます。文字列の空の文字列です。

これは別のものです。(そして、私の考えでは、より効率的です)これは、質問のコマンドと比較すると、コインの一面です。printf %.0各引数の長さについて、文字列のようなものから何でも得ることができます。

大量のバイトが作成されている場合は、次のようなより高速な方法を使用できますdd

printf \\0| dd bs=64k conv=sync 

...そして、一般ファイルddのパラメータを使用すると、seek=[num]より大きな利点が得られます。上記の内容を追加すると、,unblock cbs=1nullの代わりに64kの改行が得られ、そこからおよびpaste-を使用して各行にランダムな文字列を挿入できます/dev/null。ただし、この場合、利用可能な場合は次のものを使用することもできます。

yes 'output string forever'

ddとにかく、ここにいくつかの例があります:

dd bs=5000 seek=1 if=/dev/null of=./H.txt

...作成する(または切り捨て)\0NUL現在、ディレクトリに5000バイトサイズのH.txtというパディングファイルがあります。ddオフセットを見つけ、その後のすべての内容をNULで埋めます。

<&1 dd bs=5000 conv=sync,noerror count=1 | tr \\0 H >./H.txt

...名前とサイズは同じですが、H文字で埋められたファイルを生成します。指定および変換dd時に読み取りエラーが発生した場合、少なくとも完全な空のブロックを作成する標準動作を利用します。noerrorsync(そうでなければ、count=あなたが望むものより長く持続する可能性があります)dd、意図的にstdinから書き込み専用ファイル記述子をリダイレクトします。

答え2

%.0sパラメータを次に変換ひも、一つあります。正確0です。によるとman 3 printf、この場合の精度値は次のように与えられる。

   [ ... ] the  maximum  number  of characters to be printed from a
   string for s and S conversions.

したがって、精度が0のとき、文字列パラメータ印刷がまったくありません。ただし、(型指定子の一部である)は引数Hだけ印刷されます。printfman bash

The format is reused as necessary to consume all  of  the  argu‐
ments.  If the format requires more arguments than are supplied,
the extra format specifications behave as if  a  zero  value  or
null  string,  as  appropriate,  had  been supplied. 

答え3

この場合、%.0s先行文字のインスタンスは常に印刷されますH。これを使用すると、{1..5000}シェルは次のように拡張します。

printf 'H%.0s' 1 2 3 4 ... 5000 > H.txt

つまり、printfコマンドには5000個のパラメータがあり、各パラメータに対してHを取得します。これらのパラメータは連続型でも数値型でもありません。

printf 'H%.0s' a bc fg 12 34

印刷HHHHH- これはパラメータの数であり、この場合は5です。

上記の最初の例では、省略記号は文字通り挿入されているのではなく、順序や範囲を表すために使用されました。

関連情報