Это должно работать и сортировать каждый блок на основе #
в 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'
определяет как BH
, так и TR
как разделители записей (по умолчанию \n
ewline ).
Этот блок NR>1{ seen[NR]=$0; next }
будет выполняться для всех R записей, но первой(NR
является N номер R записи ); поэтому для каждого номера записи в качестве ключа (индекса )связанного массива с именем видно значение всей записи будет установлено на него, а затем прочитано next
запись.
{ printf $0 }
она. Это будет выполнено только один раз, потому что в следующий раз NR>1
. В конце блок END{... }
будет запущен и выполнен:
TR="TR"seen[NR]
копирование последней записи из массива, вставленное в переменную с именем TR и последующее удаление ее из массива delete seen[NR]
. asort(seen)
сортирует массив , увиденный , на основе их сохраненных значений; тогда for(x in seen)
на этом массиве иprintf "BH"seen[x]
Если вы не возражаете против первой и последней строк в вашем файле, вы также можете:
sed '1d; $d' infile |awk '{printf $0(/^BT/?"\n":"#")}' |sort |tr '#' '\n'
Вы можете попробовать следующее:
awk 'FNR==1 {if (NR>1) next; print;} \
/^D/ {seq++; sid=sprintf("SEQ%07d",seq); sub(/SEQ[0-9]+/,sid); print} \
END {printf("T%05d\n",seq);}' file1.txt file2.txt
Это будет
D
, увеличьте счетчик последовательности seq
, замените существующую последовательность новым идентификатором последовательности и напечатайте строку. В конце -файла -будет напечатана сумма из последнего значения seq
.
Это решение также должно работать для более чем двух файлов.
С GNU awk для соответствия 3-го аргумента (), если вы хотите напечатать новый порядковый номер с той же шириной строки, дополненной 0 -, что и существующий ввод:
$ cat tst.awk
NR==1 && FNR==1 { print }
FNR > 2 { printf "%s%0*d%s\n", prev[1], length(prev[2]), ++seqNr, prev[3] }
{ match($0,/([^1-9]+)([0-9]+)(.*)/,prev) }
END { printf "%s%0*d\n", prev[1], length(prev[2]), seqNr }
$ awk -f tst.awk file1 file2
H20200428
DSEQ0000001USA
DSEQ0000002MEXICO
DSEQ0000003BRAZIL
DSEQ0000004USA
DSEQ0000005MEXICO
DSEQ0000006BRAZIL
T00006
что с любым awk (и сохранением массива prev[]
вместо использования скаляров для сравнения со скриптом gawk )будет:
$ cat tst.awk
NR==1 && FNR==1 { print }
FNR > 2 { printf "%s%0*d%s\n", prev[1], lgth2, ++seqNr, prev[3] }
{
match($0,/[^1-9]+/)
prev[1] = substr($0,RSTART,RLENGTH)
match($0,/[^1-9]+[0-9]+/)
lgth2 = RLENGTH - length(prev[1])
prev[3] = substr($0,RSTART+RLENGTH)
}
END { printf "%s%0*d\n", prev[1], lgth2, seqNr }
$ awk -f tst.awk file1 file2
H20200428
DSEQ0000001USA
DSEQ0000002MEXICO
DSEQ0000003BRAZIL
DSEQ0000004USA
DSEQ0000005MEXICO
DSEQ0000006BRAZIL
T00006
или, если вы хотите просто сохранить такое же количество начальных нулей, используйте GNU awk:
$ cat tst.awk
NR==1 && FNR==1 { print }
FNR > 2 { print prev[1] (++seqNr) prev[2] }
{ match($0,/([^1-9]+)[0-9]+(.*)/,prev) }
END { print prev[1] seqNr }
$ awk -f tst.awk file1 file2
H20200428
DSEQ0000001USA
DSEQ0000002MEXICO
DSEQ0000003BRAZIL
DSEQ0000004USA
DSEQ0000005MEXICO
DSEQ0000006BRAZIL
T00006
и с любым awk:
$ cat tst.awk
NR==1 && FNR==1 { print }
FNR > 2 { print prev[1] (++seqNr) prev[2] }
{
match($0,/[^1-9]+/)
prev[1] = substr($0,RSTART,RLENGTH)
sub(/[^0-9]+[0-9]+/,"")
prev[2] = $0
}
END { print prev[1] seqNr }
$ awk -f tst.awk file1 file2
H20200428
DSEQ0000001USA
DSEQ0000002MEXICO
DSEQ0000003BRAZIL
DSEQ0000004USA
DSEQ0000005MEXICO
DSEQ0000006BRAZIL
T00006