同様のファイルがあります。
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レコードの2番目のフィールドに基づいてチャンクをソートする必要があります。ブロック内の行はそのままにしておく必要があります。上記のファイルの予想出力は次のとおりです。
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
私はこれを行うための迅速で簡単な方法を見つけました。より良い方法があれば提案してください。
ヘッダーとトレーラーのレコードが削除されました。ブロック内の行の間に行区切り記号を使用して#をマージし、入れて1行にマージします。特定のフィールドで並べ替え新しい行に置き換える#
gawk '/^HC/ && line {print line; line=""} {line = line ? line"#"$0 : $0} END {print line}' input.txt | sort -t"|" -nk 13 | tr '#' '\n' > finaloutput.txt