2013-01-10 7 views
4

Я довольно новичок в кодировке UNIX, и у меня есть файл, который мне нужно прочитать в обратном порядке. Файл имеет разделы кода внутри {}. Затем мне нужно запустить awk-скрипт с этим обратным файлом в качестве ввода. У меня есть наш сотрудник службы поддержки tac, но прежде чем они это сделают, я хочу знать, будет ли он выводить то, что мне нужно, или кто-нибудь может предложить альтернативу.using tac для чтения файла в обратном порядке

Файл содержит данные в виде:

page 0 0 0 none 
{ 
    layer 0 0 0 "1line" 0 8 8 3 
    { 
     sector 0 -1 0 32 
     { 
     point_name 0 0 34543 34 44 1 1 0 
     status 1 0 1 0 1 431232 "transformer" 23 12 
     analog 1 0 1 0 1 321234 11.5 43 1 1 0 
     ... 
     ... 
     ... 
     device 1 0 1 "ground" 32 56 1 1 0 
     } 
    } 
} 

, и я хочу, чтобы сохранить {}, но поменять местами строки между {}, поэтому из пут выглядит следующим образом:

page 0 0 0 none 
{ 
    layer 0 0 0 "1line" 0 8 8 3 
    { 
     sector 0 -1 0 32 
     { 
     device 1 0 1 "ground" 32 56 1 1 0 
     ... 
     ... 
     ... 
     analog 1 0 1 0 1 321234 11.5 43 1 1 0 
     status 1 0 1 0 1 431232 "transformer" 23 12 
     point_name 0 0 34543 34 44 1 1 0 
     } 
    } 
} 

Рекомендуем также , tac перезаписывает входной файл или сохраняет его как другой файл?

ответ

1

Как и большинство UNIX (стиль) инструментов tac ни переписывает Orignal файла или записывает новую, он печатает stdout, чтобы написать новый файл с tac вы бы использовать перенаправление tac file > newfile это позволит сэкономить обращенную file в newfile , Вы не можете делать то, что вам нужно, только с tac, вам нужен скрипт.

Вот один в awk:

{ 
    # store each line in the array line 
    line[n++] = $0 
} 

/{/ { 
    # get the line number of the last line containing { 
    first=NR 
} 

!/}/ { 
    # get the line number of the last line not containing } 
    last=NR 
} 

END { 
    # print first section in order 
    for (i=0;i<first;i++) 
     print line[i] 
    # print second section in reverse order 
    for (i=last-1;i>=first;i--)  
     print line[i] 
    # print last section in order 
    for (i=last;i<NR;i++) 
     print line[i] 
} 

Сохранить в файл сказать reverse затем запустить awk -f reverse file:

$ awk -f reverse file 
page 0 0 0 none 
{ 
    layer 0 0 0 "1line" 0 8 8 3 
    { 
     sector 0 -1 0 32 
     { 
     device 1 0 1 "ground" 32 56 1 1 0 
     ... 
     ... 
     ... 
     analog 1 0 1 0 1 321234 11.5 43 1 1 0 
     status 1 0 1 0 1 431232 "transformer" 23 12 
     point_name 0 0 34543 34 44 1 1 0 
     } 
    } 
} 

Использование перенаправления для создания нового файла awk -f reverse file > newfile.

+0

Без какой-либо модификации это не будет выполнено для чего-либо другого, кроме заданного точного ввода - что, вероятно, не соответствует требованиям OP. Я бы помог вам исправить это, но это действительно не так, как вы хотели бы решить эту проблему. Кроме того, это 2:30 утра, и я пойду спать ... ночью. – Steve

+0

@steve, как я понял вопрос, код хорошо формат, никогда не '}', предшествующий '{', поэтому я сохранил сценарий простым и понятным. –

1

tac просто меняет порядок строк файла, поэтому вам нужно что-то более мощное, чтобы выполнить то, что вы хотите. Кроме того, все инструменты оболочки не включают в себя средства перезаписи входного файла без использования файлов «temp». Некоторые инструменты (например, sed, Perl и т. Д.) Имеют так называемое «редактирование на месте», что при отсутствии суффикса файла резервной копии даст чистый результат перезаписи файла.

Чтобы выполнить то, что вы хотите, я бы рекомендовал использовать awk.Бегите как:

awk -f script.awk file > newfile 

Для перезаписи входного файла, используя временный файл, выполните команду:

awk -f script.awk file > temp && mv temp file 

Содержание script.awk:

/{/ { 
    print (a ? a ORS : "") $0 
    f=1; a=b="" 
    next 
} 

f && !/}/ { 
    a = (a ? a ORS : "") $0 
    b = $0 (b ? ORS b : "") 
    next 
} 

/}/ && b { 
    print b ORS $0 
    a=b=f="" 
    next 
}1 

Результаты:

page 0 0 0 none 
{ 
    layer 0 0 0 "1line" 0 8 8 3 
    { 
     sector 0 -1 0 32 
     { 
     device 1 0 1 "ground" 32 56 1 1 0 
     ... 
     ... 
     ... 
     analog 1 0 1 0 1 321234 11.5 43 1 1 0 
     status 1 0 1 0 1 431232 "transformer" 23 12 
     point_name 0 0 34543 34 44 1 1 0 
     } 
    } 
} 

С другой стороны, вот один лайнер:

awk '/{/ { print (a ? a ORS : "") $0; f=1; a=b=""; next } f && !/}/ { a = (a ? a ORS : "") $0; b = $0 (b ? ORS b : ""); next } /}/ && b { print b ORS $0; a=b=f=""; next }1' file 

Объяснение:

Первый блок кода спрашивает, если строка содержит открывающую фигурную скобку. Если да, напечатайте что-либо в записи «a», за которой следует текущая запись (строка, содержащая открывающую скобу). Установите флаг, удалите записи «a» и «b» и пропустите обработку остальной части кода.

Второй блок будет выполнен в том случае и только в том случае, если флаг установлен, и строка не содержит закрывающей фигурной скобки. Теперь мы создаем две записи «a» и «b». Напомним, что запись «a» будет напечатана, если в строке есть открывающая скобка. Поэтому он должен быть построен в ориентации «от начала до конца». Затем мы создаем запись 'b' в ориентации 'end to start'. 'next' затем пропускает обработку остальной части кода.

Третий блок будет выполнен, если строка содержит замыкающую фигуру и запись «b» (напомните, что это запись в обратной ориентации). Затем мы печатаем запись «b», за которой следует текущая строка (линия с закрывающей скобкой). Удалите записи «a», «b» и сбросьте флаг. 'next', чтобы пропустить обработку остальной части кода. «1» на конце позволяет печать по умолчанию.

+0

Хороший ответ ';)' ум, описывающий скрипт? –

+0

@sudo_O: Я добавил объяснение. Честно говоря, код имеет смысл (по крайней мере, для меня), чем объяснение. НТН. – Steve

+0

Благодарим вас за быстрые ответы, я попробую их обоих позже и дам вам знать, решит ли они мою проблему – user1966709