大きなテキストブロックセット内で2つのテキストブロックを逆方向に並べ替える

大きなテキストブロックセット内で2つのテキストブロックを逆方向に並べ替える

ヘッダーごとにチャンクに分割されたデータのリストがあります。タイトルの先頭と末尾には6つの「=」記号があります。表示できるタイトルの数は制限されていますが、毎回すべてのタイトルが表示されるわけではありません。しかし、毎回同じ順序で表示されます。各ブロックのデータ量はさまざまです。このデータセットでは、2つの特定のテキストブロックの順序を変更したいと思います。 (説明:ブロック内のデータの順序ではなく、ブロックが印刷される順序)

編集:別の説明:異なるヘッダーの数が制限されており、内容を知っていますが、ファイルの場所は不明な2つの特定のヘッダーを反転したいと思います。どちらか一方のみが発生する場合も、どちらも発生しない場合もあります。表示される場合は、常に同じ順序で直後に表示されます。

入力例:

======abc======
data1
data2
data3
======def======
data4
======ghi======
data5
data6
======jkl======
data7
======mno======
data8

希望の出力:

======abc======
data1
data2
data3
======def======
data4
======jkl======
data7
======ghi======
data5
data6
======mno======
data8

各ヘッダーの前に空行を追加し、次のようなsed '/======.*======/i\\'ものを使用する場合この回答役に立つかもしれませんが、Perlを使ったことがないので、私が望むように修正する方法がわかりません。私もawkがこれを行うことができると思います。

答え1

awkを使用してください。

$ cat tst.awk
/^======[^=]+======$/ {
    key = $0
    gsub(/=/,"",key)
    keys[++numKeys] = key
}
{ key2val[key] = key2val[key] $0 ORS }
END {
    if ( (a in key2val) && (b in key2val) ) {
        tmpVal = key2val[a]
        key2val[a] = key2val[b]
        key2val[b] = tmpVal
    }
    for ( i=1; i<=numKeys; i++ ) {
        key = keys[i]
        printf "%s", key2val[key]
    }
}

$ awk -v a='ghi' -v b='jkl' -f tst.awk file
======abc======
data1
data2
data3
======def======
data4
======jkl======
data7
======ghi======
data5
data6
======mno======
data8

答え2

これを行うには、awkとsedを使用する方が簡単です。入力ファイル(ブロックと呼ぶ)から始めて、最初にjklブロックを一時ファイル(the_blockという)に転送します。

$ awk '/=jkl=/{p=1; print; next} /======/{p=0}; p>0{print}; p==0{print >"reduced"}' blocks > the_block

2つの新しいファイルを確認してください。

$ cat the_block 
======jkl======
data7

$ cat reduced 
======abc======
data1
data2
data3
======def======
data4
======ghi======
data5
data6
======mno======
data8

sedを使用して、「縮小された」ファイルの予想ブロックの最初の行の上にthe_blockを挿入して最終結果を取得します。

$ sed '/=ghi=/ {r the_block                                                                           
                  N
                }' reduced 
======abc======
data1
data2
data3
======def======
data4
======jkl======
data7
======ghi======
data5
data6
======mno======
data8

(今は一時ファイルを削除できます)

答え3

そしてGNUエディタ:

printf '%s\n' '/^======ghi======$/kx' '/^======jkl======$/;/^======/-1m'"'x-1" 'w output' | 
  ed -s input

結果:

$ pr -Tm input output 
======abc======                     ======abc======
data1                               data1
data2                               data2
data3                               data3
======def======                     ======def======
data4                               data4
======ghi======                     ======jkl======
data5                               data7
data6                               ======ghi======
======jkl======                     data5
data7                               data6
======mno======                     ======mno======
data8                               data8

答え4

使用幸せ(以前のPerl_6)

~$ raku -e 'my @a = slurp.comb( / "======" (<alpha>**3) "======" \v [ \V+ \v]+? <?before "======" | $ > /);  \
            .print for flat @a[0..1,(2..3).sort.reverse,4..*];'  file

または:

~$ raku -e 'my regex H { "======" <alpha>**3 "======" \v };  \
            my @a = slurp.comb( / <H> [ \V+ \v ]+? <?before <H> | $ > /);  \
            .print for flat @a[0..1,(2..3).sort.reverse,4..*]'  file

上記は、Perlプログラミング言語ファミリーであるRakuで書かれたソリューションです。 Rakuには、ファイルcombで探している繰り返しパターンを宣言する機能があります。split仕切り必須要素間)。どちらのソリューションも、slurpファイル全体をメモリに読み込むRakuの機能を使用します(改行なし)。

メモ:[ … ]-sigiled 配列でインデックスを再配列するとき@これはflat10の結果シーケンスに非常に重要です。Raku(Perlとは異なり)は、デフォルトでは自動的にマージされないためです。

  • 最初のソリューションでは、まずヘッダー行を見つけて"======" (<alpha>**3) "======" \vから、本文パターンを見つけます[ \V+ \v ]+?。これは\v組み込みの垂直スペース文字クラスで、\V組み込みです。いいえ垂直スペース文字クラスです。これは?一致を貪欲にしないようにします。これは\V+、少なくとも1つのボディラインが必要であることを意味します(\V*許容される場合は0ボディラインに変更)。

  • 2番目のソリューションでは、ヘッダー行パターンは独自のH正規表現パターンに抽象化されます。したがって、combマッチャーで次の呼び出しを<H>使用して/…/ヘッダーパターンを取得できます。このパターンを必要に応じて簡単に作成したり(たとえば)、"======"他のファイルに適用したりできます。したがって、このコードはかなり一般的な解決策になる可能性があります。

入力例:

======abc======
data1
data2
data3
======def======
data4
======ghi======
data5
data6
======jkl======
data7
======mno======
data8

出力例:

======abc======
data1
data2
data3
======def======
data4
======jkl======
data7
======ghi======
data5
data6
======mno======
data8

Rakuにはいくつかの便利な機能があり、そのうちの1つは組み込みpairs機能を使用する機能です。 2番目の便利な機能は、rakuRakuの内部データ表現を取得するためにオブジェクトを呼び出すことです。 Rakuのput呼び出しと組み合わせ(\n改行文字で印刷):

~$ raku -e 'my regex H { "======" <alpha>**3 "======" \v };  \
            my @a = slurp.comb( / <H> [ \V+ \v]+? <?before <H> | $ > /).pairs;  \
            .raku.put for flat @a[0..1,(2..3).sort.reverse,4..*];'  file
0 => "======abc======\ndata1\ndata2\ndata3\n"
1 => "======def======\ndata4\n"
3 => "======jkl======\ndata7\n"
2 => "======ghi======\ndata5\ndata6\n"
4 => "======mno======\ndata8\n"

#OR (flattening by a different method):

~$ raku -e 'my regex H { "======" <alpha>**3 "======" \v };  \
            my @a = slurp.comb( / <H> [ \V+ \v]+? <?before <H> | $ > /).pairs;  \
            .raku.put for @a[flat(0..1;(2..3).sort.reverse;[email protected])];'  file
0 => "======abc======\ndata1\ndata2\ndata3\n"
1 => "======def======\ndata4\n"
3 => "======jkl======\ndata7\n"
2 => "======ghi======\ndata5\ndata6\n"
4 => "======mno======\ndata8\n"

https://docs.raku.org
https://raku.org

関連情報