AWKを使用して管理される4行段落セット

AWKを使用して管理される4行段落セット

4行の複数の段落(2000以上)のファイルがあります。次の例に示すように、各段落に対して角括弧の内容を一致させる必要があります。

だから、各段落ごとに、

  • エントリは最初の2行です。
  • 3行目の場合、角カッコ間の現在の内容は、2行目の角カッコ間の内容に置き換えられる。
  • 4行目では、角カッコ間の現在の内容は、最初の行の角カッコの間の内容に置き換えられます。

私はそれが十分に明確であることを願っています。

--入力する--

A1 [A3 A4 A5] A2
B1 [B3 B4 B5] B2
C1 [C3 C4] C2
D1 [D3 D4] D2

E1 [E3 E4 E5] E2
F1 [F3 F4 F5] F2
G1 [G3 G4] G2
H1 [H3 H4] H2

--算出--

A1 [A3 A4 A5] A2
B1 [B3 B4 B5] B2
C1 [B3 B4 B5] C2
D1 [A3 A4 A5] D2

E1 [E3 E4 E5] E2
F1 [F3 F4 F5] F2
G1 [F3 F4 F5] G2
H1 [E3 E4 E5] H2

解決策はありますか? awkとgsubを使用しているようですが、それは問題です。

答え1

awk -F[][] -vOFS= '++i==1 {a=$2} i==2 {b=$2} i==3 {$2="[" b "]"} i==4 {$2="[" a "]"} !NF {i=0} 1' input.txt

角かっこをフィールド区切り文字として使用し、代替ソース/ターゲットは$2

各行にこれを増やし、i段落間でゼロにリセットします。 (1〜4)の値はi何をすべきかを示します$2

答え2

$ cat tst.awk
match($0,/\[.*]/) {
    idx = (NR - 1) % 5 + 1
    sect[idx] = substr($0,RSTART,RLENGTH)
    if ( idx == 3 ) {
        $0 = $1 OFS sect[2] OFS $NF
    }
    else if ( idx == 4 ) {
        $0 = $1 OFS sect[1] OFS $NF
    }
}
{ print }

$ awk -f tst.awk file
A1 [A3 A4 A5] A2
B1 [B3 B4 B5] B2
C1 [B3 B4 B5] C2
D1 [A3 A4 A5] D2

E1 [E3 E4 E5] E2
F1 [F3 F4 F5] F2
G1 [F3 F4 F5] G2
H1 [E3 E4 E5] H2

上記のコードは文字列置換を実行するので、角かっこ内の部分に正規表現メタ文字や逆参照が含まれていても機能します。

答え3

角括弧の間に正規表現の特殊文字がないと仮定するGNU awk:

$ gawk -vRS= '
  BEGIN{OFS=FS="\n"}
  match($1,/\[[^]]*\]/,x) && match($2,/\[[^]]*\]/,y) {
    sub(/\[[^]]*\]/,y[0],$3);
    sub(/\[[^]]*\]/,x[0],$4);
    printf "%s%s", $0, RT
  }
  ' file
A1 [A3 A4 A5] A2
B1 [B3 B4 B5] B2
C1 [B3 B4 B5] C2
D1 [A3 A4 A5] D2

E1 [E3 E4 E5] E2
F1 [F3 F4 F5] F2
G1 [F3 F4 F5] G2
H1 [E3 E4 E5] H2

交換に等を使用しなければならないことを除いて、GNUではなくawkでも本質的に可能であり、次を使用して元の入力レコード区切り文字を復元することはsubstr($1,RSTART,RLENGTH)できません。RT

awk '
  BEGIN{RS=""; ORS="\n\n"; OFS=FS="\n"}
  match($1,/\[[^]]*\]/) {x = substr($1,RSTART,RLENGTH)}
  match($2,/\[[^]]*\]/) {y = substr($2,RSTART,RLENGTH)}
  {
    sub(/\[[^]]*\]/,y,$3);
    sub(/\[[^]]*\]/,x,$4);
    print
  }
  ' file

答え4

perl -00pe 's/(.*)(\[.*\])(.*\n)
              (.*)(\[.*\])(.*\n)
              (.*)(\[.*\])(.*\n)
              (.*)(\[.*\])(.*\n)
             /$1$2$3$4$5$6$7$5$9$10$2$12/x' input1

perl -00pe-- 各段落ごと。

RE の各行は入力段落行と一致し、関連セクションで区切られます。交換グループ内では、部品を再注文するだけです。

混乱させて申し訳ありません...

関連情報