Awk или Sed: аннотация файла

Привет, мой ТАКОЙ друг, мой вопрос:

Спецификация: аннотируйте поля FILE_2 соответствующей позицией FILE_1.
Поле помечается и, следовательно, идентифицируется парой разделителей.

Я выполнил эту работу на питоне до того, как познакомился с awk и sed, написав пару сотен строк кода. Теперь я хочу увидеть, насколько мощными и эффективными могут быть awk и sed. Покажите мне какой-нибудь шедевр awk или sed, пожалуйста!

Пары разделителей можно настроить в FILE_3, но давайте предположим, что первый разделитель в паре
'Маркер (номер i) старт', а другой
'Маркер (номер i) готов'

Пример:
|-----------------FILE_1------------------|
text text text
text blabla
Marker_1_start
Marker_1_done
любой текст
между blabla
Marker_2_start
Marker_2_done
текст текст

|-----------------FILE_2------------------|
Marker_1_start< br> 11
1111
Marker_1_done
Marker_2_start
2222
22
Marker_2_done

Ожидаемый результат:
|-----------------FILE_Out------------------|
text text text
text blabla
Marker_1_start
11
1111
Marker_1_done
любой текст
между blabla
< strong>Marker_2_start
2222
22
Marker_2_done
text text


person lukmac    schedule 05.01.2011    source источник
comment
Что вы имеете в виду под "звездочками"? Я не вводил ни одной звездочки.   -  person lukmac    schedule 06.01.2011


Ответы (3)


Есть несколько подходов к этому. Я предполагаю, что FILE_2 меньше, чем FILE_1, и имеет разумный размер.

#!/usr/bin/awk -f
FNR == NR {
    if ($0 ~ /^Marker.*start$/) {
        flag = 1
        idx = $0
        next
    }
    if ($0 ~ /^Marker.*done$/) {
        flag = 0
        nl = ""
        next
    }
    if (flag) lines[idx] = lines[idx] nl $0
    nl = "\n"
    next
}
{
    print
    if (lines[$0]) print lines[$0]
}

Чтобы запустить его:

./script.awk FILE_2 FILE_1
person Dennis Williamson    schedule 05.01.2011
comment
Вы должны использовать idx = $0, так как позже вы будете использовать lines[$0]. Если его текст маркера содержит пробелы, ваш код сломается как есть. В любом случае, спасибо за идею конкатенации, я обязательно буду использовать ее с этого момента, так что +1 за это - person SiegeX; 06.01.2011
comment
Денис, я думаю, ты попал в самую точку! Отлично! ‹br› Кстати, SiegeX прав насчет использования ide=$0. - person lukmac; 06.01.2011

Теперь я хочу увидеть, насколько мощными и эффективными могут быть awk и sed.

Для такого типа задач очень эффективно. Я уверен, что мой код можно еще уменьшить.

#!/bin/bash

awk '
  FNR == NR {
     if ($0 ~ /Marker_1_start/){m1=1;next}
     if ($0 ~ /Marker
$ ./filemerge.sh
text text text
text blabla
Marker_1_start
11
1111
Marker_1_done
any text
in between blabla
Marker_2_start
2222
22
Marker_2_done
text text
start/){m2=1;next} if ($0 ~ /Marker_1_done/){m1=0} if ($0 ~ /Marker
$ ./filemerge.sh
text text text
text blabla
Marker_1_start
11
1111
Marker_1_done
any text
in between blabla
Marker_2_start
2222
22
Marker_2_done
text text
done/){m2=0} if(m1){a[i++]=$0} if(m2){b[j++]=$0} } FNR != NR { if ($0 ~ /Marker_1_start/){print;n1=1} if ($0 ~ /Marker
$ ./filemerge.sh
text text text
text blabla
Marker_1_start
11
1111
Marker_1_done
any text
in between blabla
Marker_2_start
2222
22
Marker_2_done
text text
start/){print;n2=1} if ($0 ~ /Marker_1_done/){n1=0} if ($0 ~ /Marker
$ ./filemerge.sh
text text text
text blabla
Marker_1_start
11
1111
Marker_1_done
any text
in between blabla
Marker_2_start
2222
22
Marker_2_done
text text
done/){n2=0} if(n1) for (k = 0; k < i; k++) print a[k] else if(n2) for (l = 0; l < j; l++) print b[l] else print }' ./file_2 ./file_1

Вывод

$ ./filemerge.sh
text text text
text blabla
Marker_1_start
11
1111
Marker_1_done
any text
in between blabla
Marker_2_start
2222
22
Marker_2_done
text text
person SiegeX    schedule 05.01.2011
comment
@Деннис, его не пригласили на вечеринку - person SiegeX; 06.01.2011

person    schedule
comment
@SiegeX, операторы печати должны быть именно в таком порядке, чтобы начало маркера выводилось перед телом маркера. @Денис, да. - person glenn jackman; 06.01.2011
comment
@Dennis: или {print} избыточно, выбирай! - person William Pursell; 29.08.2012