2013-06-11 3 views
3

Я пытаюсь разбить файл, используя AWK в одной строке, но код ниже, с которым я пришел, работает неправильно.AWK split для нескольких строк разделителей

awk ' 
BEGIN { idx=0; file="original_file.split." } 
/^REC_DELIMITER.(HIGH|TOP)$/ { idx++ } 
/^REC_DELIMITER.TOP$/,/^REC_DELIMITER.(HIGH|TOP)$/ { print > file sprintf("%03d", idx) } 
' original_file 

Тестовый файл "original_file":

REC_DELIMITER.TOP 
lineA1 
lineA2 
lineA3 
REC_DELIMITER.HIGH 
lineB1 
lineB2 
lineB3 
REC_DELIMITER.TOP 
lineC1 
lineC2 
lineC3 
REC_DELIMITER.HIGH 
lineD1 
lineD2 
lineD3 

AWK код выше для REC_DELIMITER.TOP и он дает мне эти файлы:

original_file.split.001: 
REC_DELIMITER.TOP 

original_file.split.003: 
REC_DELIMITER.TOP 

однако, я пытаюсь для получения:

original_file.split.001: 
REC_DELIMITER.TOP 
lineA1 
lineA2 
lineA3 

original_file.split.003: 
REC_DELIMITER.TOP 
lineC1 
lineC2 
lineC3 

Будет отсутствовать ее запись разделители, и в случае необходимости, мы можем работать для них, как REC_DELIMITER.HIGH, таким образом, получать файлы, как показано ниже:

original_file.split.002: 
REC_DELIMITER.HIGH 
lineB1 
lineB2 
lineB3 

original_file.split.004: 
REC_DELIMITER.HIGH 
lineD1 
lineD2 
lineD3 

Любая помощь ребята очень ценят, я пытался получить эту работу за последние несколько дней и код AWK выше - лучшее, что я смог получить. Мне нужна помощь мастеров AWK. :)

Спасибо!

+1

Cramming 4 строки кода на одну строку не полезны для удобства чтения. Также избавиться от HTML из вашего образца ввода/вывода, если это действительно не присутствует в ваших файлах. –

+0

спасибо .. HTML удален. – Jose

ответ

-2

Я не очень привык к AWK, однако ответ пластики поставил меня в правильном направлении, и я, наконец, получил AWK-скрипт, работающий как требования.

В нижеприведенном коде, первый IF включает эхо-сигнал в 0, если обнаружен дефинитор. Второй IF включает эхо-сигнал в 1, если найденный разграничитель найден, тогда нужные из них разделены на файл.

Я знаю, что regex может быть чем-то вроде /^(REC_(DELIMITER\.(TOP|HIGH|LOW)|NO_CATEGORY)$/, но так как regex создается динамически с помощью shellscript, который читает из определенного файла список разделителей, он будет больше похож на AWK ниже.

awk 'BEGIN { 
    idx=0; echo=1; file="original_file.split." 
} 
{ 
    #All the delimiters to consider in given file 
    if($0 ~ /^(REC_DELIMITER.TOP|REC_DELIMITER.HIGH|REC_DELIMITER.LOW|REC_NO_CATEGORY)$/) { 
    echo=0 
    } 
    #Delimiters that should actually be pulled 
    if($0 ~ /^(REC_DELIMITER.HIGH|REC_DELIMITER.LOW)$/ { 
    idx++; echo=1 
    } 
    #Print to a file is match wanted delimmiter 
    if(echo) { 
    print > file idx 
    } 
}' original_file 

Спасибо всем.Я очень ценю это.

+0

Думайте, что это немного не означает, что вы ответили на свое решение. – wmorrison365

5

Вы можете попробовать что-то вроде этого:

awk ' 
/REC_DELIMITER\.TOP/ { 
    a=1 
    b=0 
    file = sprintf (FILENAME".split.%03d",++n) 
}  
/REC_DELIMITER\.HIGH/ { 
    b=1 
    a=0 
    file = sprintf (FILENAME".split.%03d",++n) 
} 
a { 
    print $0 > file 
}  
b { 
    print $0 > file 
}' file 
3

Вам нужно что-то вроде этого (непроверенное):

awk -v dtype="TOP" ' 
BEGIN { dbase = "^REC_DELIMITER\\."; delim = dbase dtype "$" } 
$0 ~ dbase { inBlock=0 } 
$0 ~ delim { inBlock=1; idx++ } 
inBlock { print > sprintf("original_file.split.%03d", idx) } 
' original_file 
+0

действительно здорово это предложенное решение, но, к сожалению, я не могу использовать Dbase = «^ REC_DELIMITER \\. разделители должны измениться ... только файл структура не изменится. Так будет файлы с различными разделителями – Jose

+0

Затем просто установите «delim» явно используя -v вместо того, чтобы строить его из частей. Но если разделители могут быть чем угодно, как вы знаете, когда строка содержит разделитель или нет? Я имею в виду, если вы ищете «REC_DELIMITER». TOP ", и вы найдете текст« REC_DELIMITER.HIGH », как вы отличаете его от любой другой строки, которая не содержит« REC_DELIMITER.TOP »? –

+0

. Разделители считываются из другого файла .. в соответствии с тем, что обрабатывается. почему это может быть что угодно. Я, наконец, получил работу, как ожидалось. ou для всей помощи. Я ценю это! – Jose

1

Я сделал некоторые изменения, чтобы различные разделители перейти к их собственному файлу, даже когда они появляются позже в файле. сделать файл как splitter.awk с ниже содержимым, то CHMOD + х и запустить его с ./splitter.awk original_file

#!/usr/bin/awk -f 
BEGIN { 
    idx=0; 
    file="original_file.split."; 
    out="" 
} 
{ 
    if($0 ~ /^REC_DELIMITER.(TOP|HIGH)/){ 
    if (!cnt[$0]) { 
     cnt[$0] = ++idx; 
    } 
    out=cnt[$0]; 
    } 
    print > file sprintf("%03d", out) 
} 
+0

Спасибо! Ваш ответ поставил меня в правильном направлении, и я, наконец, получил AWK-скрипт, работающий как требования. – Jose

2
awk -vRS=REC_DELIMITER '/^.TOP\n/{print RS $0 > sprintf("original_file.split.%03d",n)};!++n' original_file 

(Дайте или взять дополнительный символ новой строки в конце.)

Как правило, когда ввод предполагается рассматривать как серию многострочных записей со специальной строкой в ​​качестве разделителя, самым прямым подходом является установка RS (и часто ORS) на этот разделитель.

Обычно вы хотите добавить новые строки в начало и/или конец, но этот случай немного особенный, так что без них легче.

Отредактировано для добавления: для этого вам понадобится GNU Awk. Стандартный Awk рассматривает только первый символ RS.

Смежные вопросы