4

たとえば、a11b12c22d322 e...ブレークのフィールドが数字またはスペースである行がある場合、それを次のように変換します。

a
b
c
d
e
...

sed行全体をメモリに読み込む必要があります。1行がギガバイトの場合、効率が悪く、十分なメモリがないとジョブを実行できません。

編集:

grep、tr、Awk、perl、およびpythonが大きなファイルを読み取る際にメモリをどのように操作するかを誰かが説明できますか?彼らは一度にどのくらいの量のコンテンツをメモリに読み込みますか?

4

4 に答える 4

6

使用する場合gawk(Linux のデフォルトawkだと思います)、RSパラメーターを使用して、複数桁の数字またはスペースが改行ではなく行末記号として認識されるように指定できます。

awk '{print}' RS="[[:digit:]]+| +" file.txt

2 番目の質問については、これらのプログラムはすべて、一定のバイト数を読み取り、内部バッファーで行区切り記号のアイデアを検索して、一度に 1 行を読み取るように見えるようにする必要があります。行の終わりを検索している間に大量のデータを読み取らないようにするには、行の終わりのプログラムの考え方を変更する必要があります。

ほとんどの言語でこれを行うことができますが、指定できるのは 1 文字だけです。gawk正規表現を指定して行末文字を認識できるようにすることで、簡単になります。これにより、固定サイズのバッファーと行末検索を自分で実装する必要がなくなります。

于 2013-01-27T19:01:44.707 に答える
4

最速... gccの助けを借りてそれを行うことができます。これは、指定された場合は指定されたファイル名から、そうでない場合は標準入力からデータを読み取るバージョンです。getchar()これでも遅すぎる場合は、 and putchar()(マクロである可能性があり、最適化する必要があります) を独自のバッファリング コードに置き換えることで、高速化できるかどうかを確認できます。馬鹿げたことをしたい場合は、さらに高速にするために 3 つのスレッドを用意する必要があります。そのため、カーネルは次のデータ ブロックを 1 つのコアでコピーし、別のコアが処理を行い、3 つ目のコアが処理された出力をカーネルにコピーします。

#!/bin/bash

set -e

BINNAME=$(mktemp)

gcc -xc -O3 -o $BINNAME - <<"EOF"
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
    int sep = 0;

    /* speed is a requirement, so let's reduce io overhead */
    const int bufsize = 1024*1024;
    setvbuf(stdin, malloc(bufsize), _IOFBF, bufsize);
    setvbuf(stdout, malloc(bufsize), _IOFBF, bufsize);
    /* above buffers intentionally not freed, it doesn't really matter here */

    int ch;
    while((ch = getc(stdin)) >= 0) {
        if (isdigit(ch) || isspace(ch)) {
            if (!sep) {
                if (putc('\n', stdout) == EOF) break;
                sep = 1;
            }
        } else {
            sep = 0;
            if (putc(ch, stdout) == EOF) break;
        }
    }

    /* flush should happen by on-exit handler, as buffer is not freed,
       but this will detect write errors, for program exit code */
    fflush(stdout); 

    return ferror(stdin) || ferror(stdout);
}
EOF

if [ -z "$1" ] ; then
  $BINNAME <&0
else
  $BINNAME <"$1"
fi

編集: たまたま GNU/Linux stdio.h を見て、いくつかのメモ: putchar/getcharはマクロではありませんが、putc/getcであるため、代わりにそれらを使用すると、わずかな最適化が行われる可能性があり、おそらく 1 つの関数呼び出しを回避し、これを反映するようにコードを変更しました。また、 のリターン コードのチェックを追加putcしました。

于 2013-01-27T20:16:24.743 に答える
3

grep:

$ grep -o '[^0-9 ]' <<< "a11b12c22d322 e"
a
b
c
d
e

sed:

$ sed 's/[0-9 ]\+/\n/g' <<< "a11b12c22d322 e"
a
b
c
d
e

awk:

$ awk 'gsub(/[0-9 ]+/,"\n")' <<< "a11b12c22d322 e"
a
b
c
d
e

ベンチマークさせていただきます。

于 2013-01-27T18:31:59.580 に答える
2

で試してくださいtr

tr -s '[:digit:][:space:]' '\n' <<< "a11b12c22d322e"

これにより、次の結果が得られます。

a 
b 
c 
d 
e
于 2013-01-27T18:29:57.973 に答える