объединить 2 файла с обновленным порядковым номером с помощью команды awk

Это должно работать и сортировать каждый блок на основе #в 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как разделители записей (по умолчанию \newline ).

  • Этот блок 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]
  • В конце печатаем скопированный TR .

Если вы не возражаете против первой и последней строк в вашем файле, вы также можете:

sed '1d; $d' infile |awk '{printf $0(/^BT/?"\n":"#")}' |sort |tr '#' '\n'
0
28.04.2020, 14:20
2 ответа

Вы можете попробовать следующее:

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.

Это решение также должно работать для более чем двух файлов.

2
19.03.2021, 02:21

С 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
1
19.03.2021, 02:21

Теги

Похожие вопросы