Используя AWK или SED, добавьте строку с точкой с запятой перед regexp

Группы строк в файле:

Types       datadata
Term        datadata
Vendor      datadata
Feature     datadata

Types       datadata
Term        datadata
Feature     datadata

Types       datadata
Feature     datadata

Первая группа строк в порядке. Во второй группе мне нужно добавить строку для vendor. Для третьей группы мне нужно добавить две строки для term и vendor. Я искал похожие вопросы, но не нашел правильного решения. Это заголовки для данных, которые следуют справа в той же строке, поэтому я не могу использовать простой поиск и замену.

Желаемый результат:

Types      datadata
Term       datadata
Vendor     datadata
Feature    datadata

Types      datadata
Term       datadata
;
Feature    datadata

Types      datadata
;
;
Feature    datadata

Пожалуйста, добавьте свои усилия в виде кода, который настоятельно рекомендуется на SO.

RavinderSingh13 11.12.2020 04:01
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
1
120
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Я создал файл script.awk, содержащий этот код:

function print_key(key)
{
    if (key in saved)
        print saved[key]
    else
        print ";"
}
function process_data()
{
    if (nsaved > 0)
    {
        print_key("Types")
        print_key("Term")
        print_key("Vendor")
        print_key("Feature")
        print ""
    }
    delete saved
    nsaved = 0
}
NF > 0  { saved[$1] = $0; nsaved++ }
NF == 0 { process_data() }
END     { process_data() }

Я запустил его на ваших примерных данных (содержащихся в файле с именем data):

$ awk -f script.awk data
Types       datadata
Term        datadata
Vendor      datadata
Feature     datadata

Types       datadata
Term        datadata
;
Feature     datadata

Types       datadata
;
;
Feature     datadata

$

Что делает скрипт:

  1. Определите функцию, которая принимает один аргумент, key. Если этот ключ присутствует в массиве saved, он печатается; если нет, то точка с запятой печатается на отдельной строке.
  2. Определите функцию, которая проверяет, есть ли какие-либо данные для печати, и если да, печатает каждый из ключей "Types", "Term", "Vendor" и "Feature", а затем пустую строку. Он также удаляет сохраненные данные, удаляя массив saved и возвращая nsaved к нулю.
  3. Когда количество полей больше 0, строка не пуста. Первое поле используется как ключ к массиву saved и сохраняет всю строку для последующей печати.
  4. Когда количество полей равно 0, строка пуста, и обрабатывается предыдущий блок данных.
  5. По окончании ввода обрабатывается предыдущий блок данных. Если в конце файла была пустая строка, никаких данных для обработки не будет.

Хороший сценарий! FWIW У меня возник соблазн использовать function val(key) { if (key in saved) return saved[key]; else return ";" } и print val("Types") только для того, чтобы определение значения не было связано с выполнением каких-либо действий со значением (например, его печатью), и поэтому только 1 функция выполняет всю печать. Но нбд в любом случае.

Ed Morton 11.12.2020 17:39

Это разумное изменение, @EdMorton — я мог бы даже внести его, если бы планировал серьезно использовать сценарий.

Jonathan Leffler 11.12.2020 17:42
Ответ принят как подходящий

Я бы сделал это следующим образом, пусть file.txt content будет:

Types       datadata
Term        datadata
Vendor      datadata
Feature     datadata

Types       datadata
Term        datadata
Feature     datadata

Types       datadata
Feature     datadata

затем

awk 'BEGIN{arr["Types"]=arr["Term"]=arr["Vendor"]=arr["Feature"] = ";"}
(NF>=1){arr[$1]=$0}
(NF<1){print arr["Types"];print arr["Term"];print arr["Vendor"];print arr["Feature"];print $0;
arr["Types"]=arr["Term"]=arr["Vendor"]=arr["Feature"] = ";"}
END{print arr["Types"];print arr["Term"];print arr["Vendor"];print arr["Feature"]}' file.txt

выход

Types       datadata
Term        datadata
Vendor      datadata
Feature     datadata

Types       datadata
Term        datadata
;
Feature     datadata

Types       datadata
;
;
Feature     datadata

Объяснение: В BEGIN я создаю arr с Types, Term, Vendor, Feature всеми ;. Для каждой строки с данными я устанавливаю соответствующее значение arr для этой строки. Для каждой строки без данных я печатаю содержимое arr в нужном порядке, эту строку без данных и снова устанавливаю все в arr на ;. В END я печатаю arr так же, как и для строки без данных - это требуется тогда и только тогда, когда последняя строка ваших данных не пуста.

(проверено в gawk 4.2.1)

Это все очень хорошие варианты! Я работаю со всеми тремя, чтобы увидеть, как они работают и работают в рамках моего более длинного сценария. Я выберу один в качестве ответа, но можно использовать любую из этих трех версий.

985ranch 14.12.2020 18:23
$ cat tst.awk
{ tag2val[$1] = $0 }
!NF { prt() }
END { prt() }

function prt(   n,i,tag,tags) {
    n = split("Types Term Vendor Feature",tags)
    for (i=1; i<=n; i++) {
        tag = tags[i]
        print (tag in tag2val ? tag2val[tag] : ";")
    }
    print ""
    delete tag2val
}

$ awk -f tst.awk file
Types       datadata
Term        datadata
Vendor      datadata
Feature     datadata

Types       datadata
Term        datadata
;
Feature     datadata

Types       datadata
;
;
Feature     datadata

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