使用 AWK 管理的一组 4 行段落

使用 AWK 管理的一组 4 行段落

我有一个由几段(超过2000)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 through 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)etc. 来获取替换,并且您将无法使用来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 的每一行都与一个输入段落行匹配,并将其分隔在相关部分中。在替换组中,我们只需重新排序零件即可。

抱歉造成混淆...

相关内容