Замените несколько строк одной, используя sed - PullRequest
1 голос
/ 16 марта 2020

У меня есть такой ввод:

This_is(A)
    Goto(B,condition_1)
    Goto(C,condition_2)

This_is(B)
    Goto(A,condition_3)

This_is(C)
    Goto(B,condition_1)

Я хочу, чтобы он стал таким

    (A,B,condition_1)
    (A,C,condition_2)

    (B,A,condition_3)

    (C,B,condition_1)

Кто-нибудь знает, как это сделать с помощью sed?

Ответы [ 3 ]

4 голосов
/ 16 марта 2020

Если вам не нужно действительно делать это с помощью sed, это будет работать при использовании любого awk в любой оболочке на каждом UNIX поле:

$ awk -F'[()]' '/^[^[:space:]]/{s=$2; next} {sub(/[^[:space:]]*\(/,"("s",")} 1' file
    (A,B,condition_1)
    (A,C,condition_2)

    (B,A,condition_3)

    (C,B,condition_1)
2 голосов
/ 16 марта 2020

Это возможное решение sed, где я жестко закодировал несколько битов, таких как This_is и Goto, потому что OP не уточнил, меняются ли эти строки вдоль файла в реальном файле:

sed '/^This_is/{:a;N;s/\(^This_is(\(.\)).*\)\(\n *\)Goto(\([^)]*)\)$/\1\3(\2,\4/;$!ta;s/[^\n]*\n//}' input_file

(К сожалению, со всеми этими круглыми скобками использование -E не сильно сокращает команду.)

Код будет немного более читабельным, если разбит на несколько строк:

sed '/^This_is/{
                 :a
                 N
                 s/\(^This_is(\(.\)).*\)\(\n *\)Goto(\([^)]*)\)$/\1\3(\2,\4/
                 $!ta
                 s/[^\n]*\n//
               }' os

Здесь вы можете видеть, что код выполняет действие только в строках, начинающихся с This_is; когда программа попадает в эти строки, она выполняет следующие действия:

  • Она использует команду N для добавления следующей строки в пространство шаблона (с разбросом \n s),
  • и он пытается заменить на s/…/…/, который по существу пытается выбрать x в This_is(x) и поместить его сразу после последнего Goto( на мультилинии,
  • , и он продолжает это делать если последнее действие выполнено успешно (ta переходит к :a, если s успешно) и , последняя строка не была прочитана ($! соответствует всей строке, кроме последней);
    • Действительно, это do-while l oop, где :a обозначает точку входа, где элемент управления возвращается назад, если условие while истинно, и ta - команда, которая оценивает логическое условие.
  • Когда вышеупомянутое значение l oop завершается, более короткая команда s/…/…/ удаляет ведущую строку из пространства многострочного образца, то есть строку This_is.
0 голосов
/ 17 марта 2020

Это может работать для вас (GNU sed):

sed -E '/^\S.*\(.*\)/{h;d};G;s/\S+\((.*\))\n.*(\(.*)\).*/\2,\1/;P;d' file

Если строка начинается с непробельного символа пробела и содержит символы скобки, скопируйте ее в область удержания (HS) и затем удалите ее .

В противном случае добавьте ГС, удалите небелые символы в открывающую скобку, вставьте значение между скобками из сохраненного значения, добавьте запятую и напечатайте первую строку, а затем удалите все пространство шаблона .

NB Строки, которые не соответствуют критериям замены, останутся без изменений.

Альтернативное решение, использующее параллельные GNU и sed:

parallel --pipe --recstart T -kqN1 sed -E '1{h;d};G;s/\S+\((.*)\n.*(\(.*)\).*/\2,\1/;P;d' <file
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...