25,000文字があります。
printf
私は任意の数の文字を順番に印刷するスクリプトを作成したいと思います。
説明する:
注文番号
どこ数字1〜25000の値にすることができ、この出力を得ることができます。
私はデータを別のファイルに保存したくない(最も簡単な解決策ですか?)POSIXシェルコマンドを使用することを好みます(スクリプトを可能な限り移植可能にするには:awkまたはPerlがこれを簡単にハックできることを知っています)あります)。 。
このデータを変数に保存する必要がありますか?または、コマンド()を介してprintf
プログラム全体を実行しますか?それとも別の(より良い?)解決策がありますか?なぜ他のオプションよりも1つのオプションを選択するのですか?cut
cut -c -$1
私が見落とした他の問題/警告は何ですか?
答え1
このdd
順序を考えてみましたか?これにより、必要な数のバイトをスキップし、必要な数のバイトを出力できます。
dd if=infilename bs=1 skip=sk count=ct 2>/dev/null
dd
、ファイル名を入力、ブロックサイズ1、最初にスキップSKファイルのバイトを入力してコピーします。CTバイトを標準出力に送信します(または指定されたファイルを使用します
of=name
)。通常、最後に印刷されるステータスメッセージを防ぐには、エラーメッセージをリダイレクトしてください。
答え2
移植性と信頼性を考慮して、ビッグデータを変数として保存することは良い考えではないかもしれません。awk
移植しやすい非POSIXソリューションの場合sed
。
説明する
データ量が多い場合は変数として保存しないでください。しかし、Bash自体に制限はありませんが、オペレーティングシステムに制限がある可能性があります。
「私のオペレーティングシステムで動作します」としましょう。しかし、
- オペレーティングシステムごとに制限が異なります。
- したがって、移植性を最大限にしたい場合は、なぜスクリプトがあるオペレーティングシステムで実行され、別のオペレーティングシステムでクラッシュする危険性がありますか?
- したがって、最初に変数に保存しないことでこの問題を回避してください。
次にファイルに保存します。特に、文字列を文字(または必要な最小単位)とは別の行に分割します。
次に、次を使用しますsed
。
- sedは大容量ファイル全体をロードする必要はなく、1行ずつ機能します。
sed
POSIX仕様で定義、あなたの要件を満たしていますnon-AWK
が、まだPOSIXです。
また、ファイル使用のコード保守の利点も考慮してください。スクリプトでコードをナビゲートするよりも、ファイルに保存されている行を更新する方が簡単です。
はい
ファイルには、1行に1文字(または「段階的」にしたい最小単位)のデータが含まれていますdata.lst
。
a
b
c
d
e
以下を含めることができますscript.sh
。
#!/bin/bash
stop_number="$1"
sed -n "1,${stop_number}p" data.lst
したがって、コマンドプロンプトでテストして次のことを確認してください。
$ ./script.sh 3
a
b
c
- で指定した数だけ行を
sed
印刷するために使用されます。明確にするために直接書くのではなく1
$stop_number
$stop_number
$1
$stop_number
もちろん、$1
入力したい任意の数値である位置パラメータを介して取得します。data.lst
したがって、表示される順序で3つの文字に正常に従います。data.lst
- このとき、実際の行数より大きい数字を入力すると、すべての行のみが表示されます。
- 現在は
data.lst
同じディレクトリにありますが、script.sh
望ましくない場合、実際に別の場所にある場合は、~/some/dir/data.lst
次のように調整します。~/some/dir/data.lst
したがって、実際のデータがある場合は、data.lst
このスクリプトを直接テストできます。
答え3
Tomから少し借りるには:
#!/bin/sh
skp(){ dd bs="$1" skip=1 count=0; } # direct seek to target
rd (){ dd bs="$1" skip=0 count=1; } # single read at target
tail=$(sed -ne'/^don/{=;q;}' <"$0") # skip script by line#
while [ 1 -gt "$#" ] && exit # exit when args exhausted
exec <&- <"$0" || exit # exec <"$0" each iteration
do head -n "$tail" >&3 # only consider the tail
case ${2+$1} in # test args
(*[1-9]*|-*[!0]*) # skp() when ${2++} && $1 != 0
skp "$1";esac 2>&3 # send stderr to dev/null
rd "${2-$1}" 2>&3 # else just rd() from head of offset
echo; shift ${2+"2"} # append a newline and shift args away
done 3>/dev/null # put your data below this
変数に入れないでファイルに入れてください。 25k変数はシェルが処理するのは楽しくありません。追求シングルでは、ほぼ原子的行動。したがって、バイト23843 - 24843を印刷するには、上記の操作を実行した後、次のように呼び出すことができます。
myscript 23843 1000
...最初にaは、head
ファイル記述子の共有標準からスクリプト内のすべての行を削除し、オフセットが文字列の頭部の正確に25kに設定されるようにします。それから最初の行dd
は探すオフセットは〜23kで、2番目のオフセットはdd
それを読み取ります。これが最も簡単な方法です。シェルは文字ごとに読み取るように設計されています。read
たとえば、一般的なシェルの組み込み機能は次のことを行います。1バイト read()
改行文字が見つかるまで繰り返し、改行文字が見つかるまで停止しないでください。各パラメータペアに対して1つの操作がdd
実行されます。read
これが私がテストした方法です:
# after a copy to my clipboard
ddscr(){ sh /tmp/ddscr.sh "$@"; }
{ xsel; man man; } > /tmp/ddscr.sh
{ echo show the size; ls -l /tmp/ddscr*
echo read from the top; ddscr 80
echo from the middle; ddscr 15k 160
echo from the tail; ddscr 64k | tail -n5
}
show the size
-rw-r--r-- 1 mikeserv mikeserv 37564 Dec 13 11:27 /tmp/ddscr.sh
read from the top
MAN(1) Manual pager utils MAN
from the middle
lso use manconv(1) directly.
However, this option allows you to convert several manual pages to a
single encoding without having
from the tail
31st March 2001 - present day: Colin Watson <[email protected]> is now
developing and maintaining man-db.
2.7.5 2015-11-06 MAN(1)
...そして...
ddscr 10k 10 20k 10 10250 10
fi
is option
le. If
答え4
プログラムとデータを同じファイルにラップしたい場合は、最良の方法はperl
。 ); Windowsでは標準では見つかりませんが、Windowsでも見つかりませんbash
。
#!/usr/bin/env perl
print substr(<DATA>, $ARGV[0], $ARGV[1]), "\n";
__DATA__
Just add all your text after
the __DATA__ line... no fuss, no quoting,
no tricks
たとえば、名前をselected_printとして指定し、10から始めて30文字を印刷するとします。
% selective_print 10 30