Текстовый файл в полях (столбцах) каждого n-го вхождения строки

Просмотрел уже ответившие вопросы, но не вижу в нем моего конкретного вопроса.

Я создаю таблицу Excel конфигурации Cisco и хочу получить формат прямо в полях / столбцах для импорта.

Вот формат, с измененной информацией, конечно:

zone name Zone1_HOSTNAME01 vsan XXX fcalias name STORAGEPORT_0 vsan XXX pwwn xx:xx:xx:xx:xx fcalias name STORAGEPORT_1 vsan XXX pwwn xx:xx:xx:xx:xx fcalias name STORAGEPORT_2 vsan XXX pwwn xx:xx:xx:xx:xx zone name Zone2_HOSTNAME02 vsan XXX fcalias name STORAGEPORT_3 vsan XXX pwwn xx:xx:xx:xx:xx fcalias name STORAGEPORT_4 vsan XXX pwwn xx:xx:xx:xx:xx fcalias name HOSTNAME02 vsan XXX pwwn xx:xx:xx:xx:xx 

Поэтому я хочу, чтобы все в названии зоны ZONE NAME до места «vsan» в 1 поле, а затем до следующего появления начала строки с «именем зоны» помещало каждую строку в свое поле, Затем я могу «сократить» использование разделителей, чтобы получить то, что я хочу. Таким образом, по сути, я хочу, чтобы в конце концов:

 "zone name Zone1_HOSTNAME01" "vsan" "XXX" "fcalias name" "STORAGEPORT_0 vsan XXX" "pwwn xx:xx:xx:xx:xx" "fcalias name" "STORAGEPORT_1 vsan XXX" "pwwn xx:xx:xx:xx:xx" "fcalias name" "STORAGEPORT_2 vsan XXX" "pwwn xx:xx:xx:xx:xx" 

или что-то типа того. Каждое пустое пространство может быть в своем собственном поле, так как я могу впоследствии манипулировать столбцами намного легче.

Текстовый файл имеет более 800 строк, а некоторые могут быть больше, но пока неизвестно. Самая большая проблема заключается в том, что текст, который появляется после начальной строки, начинающейся с «zone name …», может варьироваться, поэтому мне просто нужно перевести их в свои поля независимо от того, что будет дальше.

Надеюсь, что это имеет смысл, и любая помощь будет высоко оценена.

Следующий скрипт perl выводит ваш входной файл ( markizy.txt ) в формате с разделителями табуляции, так как внутри полей есть пробелы.

 #!/usr/bin/perl while(<>) { chomp; s/ +(vsan|fcalias|pwwn) */\t$1 /g ; s/ +\t/\t/; if ($. > 1 && m/^zone name/) { print $l,"\n"; $l = $_; } elsif (eof) { $l .= $_; print $l,"\n"; } else { $l .= $_; }; }; 

Встроенная переменная perl $. – это номер текущей строки, поэтому скрипт избегает печати (пустая строка), когда zone name находится в первой строке ввода. См. man perlvar для получения подробной информации об этом и многих других переменных (и их длинных псевдонимах, таких как $INPUT_LINE_NUMBER за $. ).

Сохраните его в файл, сделайте его исполняемым с помощью chmod +x и запустите его. например, с cat -T чтобы показать вкладки ( ^I ):

 $ ./markizy.pl markizy.txt | cat -T zone name Zone1_HOSTNAME01^Ivsan XXX^Ifcalias name STORAGEPORT_0^Ivsan XXX^Ipwwn xx:xx:xx:xx:xx^Ifcalias name STORAGEPORT_1^Ivsan XXX^Ipwwn xx:xx:xx:xx:xx^Ifcalias name STORAGEPORT_2^Ivsan XXX^Ipwwn xx:xx:xx:xx:xx zone name Zone2_HOSTNAME02^Ivsan XXX^Ifcalias name STORAGEPORT_3^Ivsan XXX^Ipwwn xx:xx:xx:xx:xx^Ifcalias name STORAGEPORT_4^Ivsan XXX^Ipwwn xx:xx:xx:xx:xx^Ifcalias name HOSTNAME02^Ivsan XXX^Ipwwn xx:xx:xx:xx:xx 

Труба к cat -T только для того, чтобы показать вам, что на выходе есть поля с разделителями полей (поскольку они не сильно отличаются от пробелов, в противном случае). Не используйте его при запуске на самом деле, просто перенаправляйте файл. Excel (или gnumeric или Libre Office Calc или почти любая другая электронная таблица) не должны испытывать затруднений при импорте текстового файла, разделенного TAB, – это стандартная возможность почти до тех пор, пока я помню.

Запустите его в качестве:

 ./markizy.pl markizy.txt > markizy.csv 

Возможно, вам придется сообщить Excel, что данные разделены на вкладку, а не разделены запятой на импорт, или он может обнаружить этот факт сам.

В качестве альтернативы, если вы абсолютно уверены, что ни одно из полей данных не будет содержать запятые, замените все \t s в скрипте запятыми, и вы будете разделены запятыми.

В конечном итоге может быть проще выполнить всю работу в Excel. Я вырезал и вставил ваш пример в текстовый файл и открыл его в Excel и получил следующее:

введите описание изображения здесь

Оттуда вы можете использовать команду глобального поиска и замены, чтобы внести любые изменения, которые могут вам понадобиться.

Казалось бы, некоторые поля могут быть опущены, поскольку они будут учитываться в строках, которые я создам в excel после импорта отсортированных данных. Есть я, конечно, гораздо лучшие варианты, но это заняло весь мой результат, поместил все значения в очередь на новую строку и затем удалил ненужные поля для имени vsan | pwwn | 'zone name' | fcalias и оставил меня с просто псевдонимы зоны и члена вместе с записями pwwn. Поскольку все зоны начинались с верхнего регистра Z, это упрощало также.

Код, который я использовал в одном лайнере, был:

 grep -oP '\S+' switch01-zones-20160711 | grep -Ev 'name|vsan|^01|^02|fcalias|pwwn|zone' | awk '{printf "%s%s", (/^Zone/?rs:FS), $0; rs=RS} END{print ""}' >to-import.csv 

это оставило мне приятную одиночную строку для каждой Зоны и псевдоним участника с подключенным устройством www и импортировало в Excel для построения строк, и все это в считанные минуты. Надеюсь, это помогает кому-то другому. Еще раз спасибо @cas