我有类似的文件。
HR|testing file
BH|100
B2|cat|10
B2|dog|20
BT|4
BH|105
B2|apple|10
B2|banana|20
B2|melon|10
BT|5
BH|102
B2|fan|10
B2|bulb|20
B2|washer|10
B2|dryer|10
BT|6
TR|17
我需要根据每个块的 BH 记录中的第二个字段对块进行排序。块中的行应保持完整。对于上述文件,预期输出为:
HR|testing file
**BH|100**
B2|cat|10
B2|dog|20
BT|4
**BH|102**
B2|fan|10
B2|bulb|20
B2|washer|10
B2|dryer|10
BT|6
**BH|105**
B2|apple|10
B2|banana|20
B2|melon|10
BT|5
TR|17
答案1
这应该可以工作并根据#
块BH|#
标题行并按升序对BH|100
每个BH|102
块BH|105
进行排序...
。
awk -v RS='BH|TR' 'NR>1{ seen[NR]=$0; next } { printf $0 }
END{ TR="TR"seen[NR]; delete seen[NR]; asort(seen);
for(x in seen) printf "BH"seen[x]; printf TR }' infile
HR|testing file
BH|100
B2|cat|10
B2|dog|20
BT|4
BH|102
B2|fan|10
B2|bulb|20
B2|washer|10
B2|dryer|10
BT|6
BH|105
B2|apple|10
B2|banana|20
B2|melon|10
BT|5
TR|17
这将和
RS='BH|TR'
定义为记录分隔符(默认为ewline)。BH
TR
\n
该块
NR>1{ seen[NR]=$0; next }
将为所有人运行右记录但首先(NR
是氮数量右记录);因此,对于每个记录号作为关联数组的键(索引),称为见过整个记录的值将被设置为它,然后读取next
记录。- 如果不是第一个记录,那么
{ printf $0 }
它。这只会运行一次,因为下一次NR>1
.
最后该块END{ ... }
将运行并执行以下操作:
- 这
TR="TR"seen[NR]
将从数组中复制最后一条记录插入到名为的变量中TR然后将其从数组中删除delete seen[NR]
。 - 这
asort(seen)
对数组进行排序见过基于他们保存的值;然后 - 我们循环
for(x in seen)
这个数组并printf "BH"seen[x]
- 最后我们打印复制的TR。
如果您不介意文件中的第一行和最后一行,您也可以这样做:
sed '1d; $d' infile |awk '{printf $0(/^BT/?"\n":"#")}' |sort |tr '#' '\n'
答案2
我找到了一种快速而简单的方法来做到这一点。请建议是否有更好的方法。
删除了标头和标尾记录。合并并在块中的行之间放入 # 作为行分隔符,将其合并为一行。按特定字段排序用新行替换#
gawk '/^HC/ && line {print line; line=""} {line = line ? line"#"$0 : $0} END {print line}' input.txt | sort -t"|" -nk 13 | tr '#' '\n' > finaloutput.txt