如何将模式之间的行反转到另一个文件中

如何将模式之间的行反转到另一个文件中

我在输入文件中有以下内容

#Start para
0 hello dq
1 world dq
2 welcomes dq
3 you dq
#Start para
0 how tq
1 are tq
2 you tq
#Start para
0 say dq
1 hello dq
2 to dq
3 the dq
4 world dq

我希望将其定向到另一个文件,如下所示

#Start para
3 you dq
2 welcomes dq
1 world dq
0 hello dq
#Start para
2 you tq
1 are tq
0 how tq
#Start para
4 world dq
3 the dq
2 to dq
1 hello dq
0 say dq

我该如何使用sedor来做到这一点awk?基本上我想要反转的段落#Start para。但段落的顺序应保持不变。

答案1

如果唯一的#是块的开头那么awk你可以尝试

$ awk -F'\n' 'BEGIN{RS="#"}NR>1{print "#"$1;for(i=NF-1;i>1;i--)print $i}' file

结果:

#Start para
3 you dq
2 welcomes dq
1 world dq
0 hello dq
#Start para
2 you tq
1 are tq
0 how tq
#Start para
4 world dq
3 the dq
2 to dq
1 hello dq
0 say dq

答案2

sed

sed '/#Start para/{x;G;s/^\n//;p;s/.*//;x;d};G;s/\n$//;h;$!d' input.file

对于包含以下内容的行,将其附加到by e更改#Start para的末尾:hold spacex模式空间<->保留空间然后返回数据抓住G其附加到图案。 (同样可以通过H(附加到保持)然后通过返回到模式来完成g)。如果保留空间为空,则模式空间将从空行开始,因此它会被删除s/^\n//p打印收集的行。下一个命令(直到})旨在清理保留和模式空间并转到下一行。

对于其他行(不包含#Start para),将G保留空间附加到模式,删除空行(如果保留空间为空),然后将模式空间放入保留并开始新循环,d如果不是最后一行,则删除所有内容。如果是最后一行,则默认打印形成的图案空间。

答案3

对于更保守、更少神秘的方法......

awk '
  /^#/ { printf "%s",out ; print ; out = "" }
  /^[0-9]/ { out = $0 RS out }
  END { printf "%s",out }
'

答案4

这里有一个三管齐下的方法:

sed 's/^#/\n#/' file | 
    perl -00lne '@A=split(/\n/); print shift(@A); print join "\n", reverse @A' | 
        grep .

解释

  • sed命令在以 . 开头的每行之前添加一个换行符#。这使我们能够使用 Perl 的段落模式(见下文)。
  • Perl 选项:

    • -00激活“段落模式”,“行”由 2 个字符定义\n
    • -l:删除尾随换行符并 \n在每个print调用中添加 a 。
    • -n:逐行(或在本例中逐段)读取输入文件。
    • -e:将在每行运行的脚本。
  • Perl 脚本:

    • @A=split(/\n/);:将此行(段落)拆分到数组中@A,使每个单独的行(这里是真正的行,而不是段落)成为数组的一个元素。
    • print shift(@A);@A:删除(标题行)的第一个元素并打印它。
    • print join "\n", reverse @A':将 的其余元素反转@A,用字符连接\n并打印。
  • grep .:只是一个肮脏的黑客行为,删除了添加的空白行sed。这将打印包含至少一个字符的所有行。

相关内容