在Bash中的2种模式之间按字母顺序排列

mik*_*ike 1 sorting bash awk sed

我想在Bash shell脚本中按字母顺序在2个模式之间划界线。

给定以下输入文件:

aaa
bbb
PATTERN1
foo
bar
baz
qux
PATTERN2
ccc
ddd
Run Code Online (Sandbox Code Playgroud)

我期望作为输出:

aaa
bbb
PATTERN1
bar
baz
foo
qux
PATTERN2
ccc
ddd
Run Code Online (Sandbox Code Playgroud)

首选工具是AWK“单缸套”。Sed和其他解决方案也被接受。如果包含说明,那就太好了。

fed*_*qui 7

这是asort()在GNU awk中对数组进行排序的完美案例:

gawk '/PATTERN1/ {f=1; delete a}
      /PATTERN2/ {f=0; n=asort(a); for (i=1;i<=n;i++) print a[i]}
      !f
      f{a[$0]=$0}' file
Run Code Online (Sandbox Code Playgroud)

这使用与如何在两个标记模式之间选择行类似的逻辑,使用awk / sed可能会多次发生,另外还需要:

  • 打印超出此范围的行
  • 存储此范围内的行
  • 并且当范围结束时,对其进行排序并打印。

详细说明:

  • /PATTERN1/ {f=1; delete a} 找到与PATTERN1匹配的行时,将一个标志设置为on,并清除行数组。
  • /PATTERN2/ {f=0; n=asort(a); for (i=1;i<=n;i++) print a[i]}当找到与PATTERN2匹配的行时,将标志设置为关闭。另外,对a[]包含该范围内所有行的数组进行排序并打印。
  • !f 如果该标志关闭(即不在范围内),则求值为True,以便打印该行。
  • f{a[$0]=$0}如果该标志为on,则将该行存储在数组中,a[]以便稍后使用其信息。

测试

? gawk '/PATTERN1/ {f=1} /PATTERN2/ {f=0; n=asort(a); for (i=1;i<=n;i++) print a[i]} !f; f{a[$0]=$0}' FILE
aaa
bbb
PATTERN1
bar
baz
foo
qux
PATTERN2
ccc
ddd
Run Code Online (Sandbox Code Playgroud)