私はBashでN文字ごとにファイルを読み取るためのいくつかの方法をすでに知っています。
LC_ALL=C
while read -n100 character; do
echo "$character"
done < <(cat "$@" | tr -d '\n')
echo "$character
しかし、これが動作している間、Bashまたはposix / unixツールを使用してこれを行うより速い方法を知りたいです。
これをすばやく行う方法はありますか?
答え1
コピーAdminBeeの結果少し簡単なコードを使用してください。
入力データは対応するデータと同じです。
12345678901234
567890123
4567890123456789012
34567890123
10から始めて10文字ごとに:
$ fold -w 1 file | awk 'NR % 10 == 0'
0
0
0
0
0
同じですが、1から始まります。
$ fold -w 1 file | awk 'NR % 10 == 1'
1
1
1
1
1
1
同じですが、2から始まります。
$ fold -w 1 file | awk 'NR % 10 == 2'
2
2
2
2
2
2
パフォーマンスの面では、これはawk
AdminBeeのソリューションと似ていますが、大きな入力(「大きな入力」==上記のテストデータが複数回繰り返される)では少し高速です。
fold -w 1
入力の各文字に対して1行を生成し、改行を削除します。使用される両方のコマンドは標準のPOSIXユーティリティです。
答え2
「null フィールド区切り文字」拡張のおかげで、すべての実装ではawk
なく、多くの実装で動作するこのソリューションを試してください。awk
awk -F "" -v l=100 '{last=0; for (i=1;i<=NF;i++) {if ((i+carry)%l==0) {print $i; last=i}};\
if (last) {carry=NF-last} else {carry+=(NF-l)}}' inputfile.txt
これは各文字を単一のフィールド(-F ""
)として扱い、フィールド番号モジュールで「スキップ長さ」l
(あなたの場合は100)がゼロのフィールドのみを印刷し、繰り越しを考慮しますが、改行は無視します。
1から世紀が始まるので、最初の文字はいいえ読む。あなたはそれを使用することができます
awk -F "" -v l=10 -v ofs=1 '{last=0; for (i=1;i<=NF;i++) {if ((i+carry)%l==ofs) {print $i; last=i}};\
if (last) {carry=NF-last+ofs} else {carry+=(NF-l)}}' inputfile.txt
オフセットを調整してofs
。
テストケース
Linuxシステムではgawk
、およびを使用してmawk
テストされました。nawk
- 入力ファイル
12345678901234 567890123 4567890123456789012 34567890123
- 「10番目の文字から10ごとに」出力
$ awk -F "" -v l=10 '{last=0; for (i=1;i<=NF;i++) {if ((i+carry)%l==0) {print $i; last=i}}; if (last) {carry=NF-last} else {carry+=(NF-l)}}' testfile.txt 0 0 0 0 0
- 「最初の文字から始めて10ごとに」を出力します。
$ awk -F "" -v l=10 -v ofs=1 '{last=0; for (i=1;i<=NF;i++) {if ((i+carry)%l==ofs) {print $i; last=i}}; if (last) {carry=NF-last+ofs} else {carry+=(NF-l)}}' testfile.txt 1 1 1 1 1 1