レコードの末尾に改行を追加しないプログラムによって生成されたいくつかのファイルがあります。レコード間に改行を追加したい。単純なsedスクリプトを使用してこれを実行できます。
sed -e 's/}{/}\n{/g'
問題は、入力ファイルのサイズが複数GBであるため、sedの入力行の長さが複数GBであることです。 sedはメモリに1行を保存しようとしますが、この場合は機能しません。そのオプションを試しましたが、--unbuffered
速度が遅くなり、正しく完了していないようです。
答え1
他のツールを使用して入力レコード区切り文字を設定できます。例えば
パール
perl -pe 'BEGIN{ $/="}{" } s/}{/}\n{/g' file
特殊変数
$/
は入力レコード区切り文字です。}{
で終わる行を定義するように設定します}{
。これにより、内容全体をメモリに読み込むことなく、必要なものを得ることができます。集めるか飾る
awk -v RS="}{" -vORS= 'NR > 1 {print "}\n{"}; {print}' file
同じ考えです。
RS="}{"
レコード区切り記号をに設定し}{
、}
改行{
(最初のレコードを除く)と現在のレコードを印刷します。
答え2
Perlが構造に来ます:
perl -i~ -e ' $/ = \1024;
while (<>) {
print "\n" if $closing and /^{/;
undef $closing;
s/}{/}\n{/g;
print;
$closing = 1 if /}$/;
} ' input1 input2
1024バイト単位でファイルを読み取るように$/
設定します。\1024
この変数は、1つのブロックがで終わり、次のブロックがで始まる$closing
場合を処理します。}
{
答え3
あなたがしなければならないこと:
{ <infile tr \} \\n;echo {; } | paste -d'}\n' - /dev/null >outfile
これはおそらく最も効率的なソリューションです。
これにより、{}
すべての可能なトレースデータが保護されます。別のtr
プロセスを使用すると、それを置き換えて最初のフィールドの先頭に空白行を追加できます{
。良い...
tr {} '}\n'| paste -d{\\0 /dev/null - | tr {}\\n \\n{}
したがって、最初のものはdonのサンプルデータを使用して次のようになります。
printf '{one}{two}{three}{four}' |
{ tr \} \\n; echo {; } |
paste -d'}\n' - /dev/null
{one}
{two}
{three}
{four}
{}
...二度目も...
printf '{one}{two}{three}{four}' |
tr {} '}\n'| paste -d{\\0 /dev/null - |
tr {}\\n \\n{}
#leading blank
{one}
{two}
{three}
{four}
2番目の例では、末尾の改行はありません。最初の例には1つがありますが。
答え4
次のバイナリのようなsed
ユーティリティです。bbe
この場合、sedに似た構文を使用するのが最も簡単だと思います。
私たくさんこのbbe
ユーティリティを使用することをお勧めします({uni、linu} xパッケージのインストールeqを介して利用可能apt-get
)。またはここあなたがgitの群衆の一部である場合、私は個人的に特定のリンクを確認しませんでした。
1.サポートs/before/after/
イディオム
sedに似た操作をサポートする「バイナリブロックエディタ」です。これには、s/before/after/
必要な非常に一般的な代替イディオムが含まれます。bbe
視点自体には行がないため、コマンドの末尾に「グローバルg」がないことに注意してください。
クイックテスト(参考が必要-e
):
$ echo hello | bbe -e 's/l/(replaced)/'
生産する:
he(replaced)(replaced)o
2. あなたの特定の移行}{
状況で}\n{
したがって、キャリッジリターンのない形式の百万の数字を持つ巨大なファイルがある場合は、{1}{2}{3}
簡単に置き換えて1行に1つの数字を持つことができます。{1000000}
}{
}\n{
次のコマンドを使用しますbbe
。
bbe -e 's/}{/}\n{/'
このzshループでテストしたように、尾だけをキャッチします。
$ for ((num=0; num<1000000; num++)) do; echo -n "{$num}"; done | bbe -e 's/}{/}\n{/' | tail
これにより、次のような結果が生成されます。
{999990}
{999991}
{999992}
{999993}
{999994}
{999995}
{999996}
{999997}
{999998}
{999999}
(もちろん、後続のキャリッジリターンはありません。)