Используя TAC для чтения файла в обратном порядке

Я довольно новичок в кодировании UNIX, и у меня есть файл, который мне нужно прочитать в обратной строке за строкой. В файле есть разделы кода внутри {}. Затем мне нужно запустить скрипт awk с этим обращенным файлом в качестве входных данных. У меня есть служба поддержки, устанавливающая 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 перезаписывает входной файл или сохраняет его как другой файл?

2 ответа

tac просто меняет порядок строк в файле, поэтому вам нужно что-то более мощное, чтобы выполнить то, что вы хотите. Кроме того, все инструменты оболочки не включают средства перезаписи входного файла без использования временных файлов. Некоторые инструменты (например, 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" и "b" и пропустите обработку остальной части кода.

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

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

Как и большинство инструментов UNIX (стиль) tac не перезаписывает оригинальный файл и не записывает новый, он печатает в 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,

Другие вопросы по тегам