добавление возврата каретки на две строки выше шаблона - PullRequest
0 голосов
/ 02 ноября 2018

У меня есть файл журнала базы данных, который выглядит следующим образом

tbl
---
tmp1
col1|col2
---------
  22|  33
  32|  45
tbl
---
tmp2
col1|col2| col3
---------------
  22|  33|  123
  32|  45|  456

Я пытаюсь написать команду sed, которая находит строки, которые начинаются с '---' и добавляет возврат каретки двумя строками выше. Таким образом вывод выглядит так:

tbl
---
tmp1

col1|col2
---------
  22|  33
  32|  45

tbl
---
tmp2

col1|col2| col3
---------------
  22|  33|  123
  32|  45|  456

Возможно ли это сделать с помощью sed? Если так, то как?

Ответы [ 2 ]

0 голосов
/ 03 ноября 2018

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

sed -e 'N;/---\s*$/{2!i\\' -e '};P;D' file

Считайте две строки в пространство шаблона и, если вторая строка заканчивается на ---, вставьте строку над первой из строк.

N.B. Обычно это вставляло бы пустую строку в начало файла, но, проверяя, является ли вторая строка строкой 2 в файле, этого можно избежать.

Это также может быть написано:

sed 'N;/---\s*$/!P;//!D;2!i\\' file

Альтернативой последнего решения является:

sed 'N;/---[[:space:][:cntrl:]]*$/!P;//!D;2!i\\' file
0 голосов
/ 03 ноября 2018

Метод 1

Изменение ввода с помощью tac, как предлагает Sundeep, значительно облегчает эту проблему:

tac data.txt | sed '/^----*$/ {N;a\

}' | tac | sed '2,$p'

Метод 2

Это сложная проблема, связанная только с sed (по крайней мере, для меня). Я был близко, но выбрал Perl. sed завершается, так что это определенно можно перевести. Интуитивно я бы сказал, что это может быть выполнено с помощью одного дополнительного строкового буфера, и я надеюсь, что кто-то ответит с помощью реализации только для sed. Были времена, когда это просто не держалось. Было так много странных случаев, что я решил поставить в очередь весь путь:

my @queue = ();

while (<>) {
    if (/----*/) {
        do {
            print $queue[0];
            print "\n" if scalar @queue == 2;
            shift @queue;
        } while (scalar @queue);
        print;
    } else {
        push @queue, $_;
    }
}
do print shift @queue while scalar @queue;

Я начал смотреть на проблему как:

1
0
2
1
0

Числа представляют собой смещения из следующей строки ---*, где 0 - строка ----*. Если смещение равно 2, выведите новую строку.

Постановка задачи четко выражена как:
print \n before previous line if line ~ /----*/.

Как бы то ни было, вот вывод вызова & thinsp; / & thinsp;

$ perl script.pl data.txt
tbl
---
tmp1

col1|col2
---------
  22|  33
  32|  45

tbl
---
tmp2

col1|col2| col3
---------------
  22|  33|  123
  32|  45|  456
...