#sed
#sed
Вопрос:
Контекст
Например, у меня есть этот тестовый файл foo.py
:
#!/usr/bin/env python3
'''foo'''
# comment
import ...
# [END import]
import ...
# [END import]
import ...
# [END import]
# [END import]
import even...
# [END import]
# [END import]
import odd...
# [END import]
# [END import]
Ожидаемый
Я хотел бы удалить пустую строку перед # [END import
#!/usr/bin/env python3
'''foo'''
# comment
import ...
# [END import]
import ...
# [END import]
import ...
# [END import]
# [END import]
import even...
# [END import]
# [END import]
import odd...
# [END import]
# [END import]
Может кто-нибудь дать мне рабочую версию с использованием sed и / или объяснить, почему следующее не сработало
Тест 0
sed '$!N;s/^n(# [END)/1/g' foo.py
Наблюдается
#!/usr/bin/env python3
'''foo'''
# comment
import ...
# [END import]
import ...
# [END import]
import ...
# [END import]
# [END import]
import even...
# [END import]
# [END import]
import odd...
# [END import]
# [END import]
Здесь изменилась только «четная» строка, поскольку здесь мы «потребляем» по две строки за раз
, используя N;
без возврата…
Тест 1
sed ':r;$!{N;br};s/^n(# [END)/1/g' foo.py
Наблюдается
ничего не меняется, здесь я не понимаю, почему это не работает (т. Е. Почему Шаблон не соответствует)…
Тест 2
без ^
привязки.
sed ':r;$!{N;br};s/n(# [END)/1/g' foo.py
Наблюдается
#!/usr/bin/env python3
'''foo'''
# comment
import ...
# [END import]
import ...
# [END import]
import ...# [END import]# [END import]
import even...
# [END import]
# [END import]
import odd...
# [END import]
# [END import]
обратите внимание на double #[END
в той же строке, что и ожидалось командой, но не на ожидаемый результат.
Тест 3
sed ':r;$!{N;br};s/n(n# [END)/1/g' foo.py
Наблюдается
РАБОТАЕТ, как и ожидалось, НО я не могу понять, почему он может совпадать nn
, т.Е. два последовательных возврата
Комментарии:
1. Похоже, вы удаляете все пустые строки с учетом вашего образца ввода / вывода. Если это так, то это просто
grep '.'
илиsed -n '/./p'
илиawk 'NF'
. Если это не все, что вам нужно, тогда предоставьте более репрезентативный образец ввода / вывода, включающий пустые строки, которые вы не хотите удалять.
Ответ №1:
Вам нужно будет добавить m
флаг для теста 1, чтобы ^
$
якоря и соответствовали начальному и конечному местоположениям каждой строки, в противном случае они будут соответствовать началу / концу всей строки. Это предполагает m
, что флаг поддерживается вашей реализацией, как GNU sed
это делает.
sed ':r;$!{N;br};s/^n(# [END)/1/mg'
Тест 3 работает, потому что перед пустой строкой есть новая строка как часть этой предыдущей строки. Приведенный ниже пример может помочь вам лучше визуализировать его:
$ printf 'anbncn'
a
b
c
$ printf 'anbnncn'
a
b
c
С помощью perl:
perl -0777 -pe 's/nKn(?=# [END)//g'
-0777
будет отображать весь ввод в виде одной строкиnKn(?=# [END)
будет соответствовать новой строке при условии, что до и# [END
после этой новой строки есть символ новой строки
Другой вариант с GNU sed
, не нужно читать весь файл за один раз.
sed '/^$/{N; s/n(# [END)/1/; P; D}'
/^$/
будет соответствовать пустой строкеN
добавьте следующую строку в пространство шаблонаs/n(# [END)/1/
удалите новую строку, если требуется совпадение регулярных выражений
P
и D
здесь имеют решающее значение, поэтому я процитирую руководство:
P Распечатайте часть пространства шаблона до первой новой строки.
D Если пространство шаблона не содержит новой строки, запустите обычный новый цикл, как если бы была выдана команда d. В противном случае удалите текст в пространстве шаблонов до первой новой строки и перезапустите цикл с результирующим пространством шаблонов, не читая новую строку ввода.
Комментарии:
1. в тесте 3 сопоставление
nna
, похоже, потребляет для меня 3 строки, т.Е. Я должен был бы использоватьN;N;
…2. Я не знаком с
/m
флагом вsed
; этоsed
расширение GNU? Справочная страница молчит.3. @tripleee только что проверил руководство по GNU sed , и там действительно сказано, что это расширение GNU.. кроме того,
`
и'
всегда будет соответствовать началу / концу строки
Ответ №2:
Это может сработать для вас (GNU sed):
sed 'N;/^n# [END import]/!P;D' file
Откройте окно из 2 строк по всему файлу, и если первая строка пуста, а вторая строка — # [END import]
не печатайте первую строку.
Примечание. Идиома N;...;P;D
печатает все строки в файле, но позволяет программисту обрабатывать около 2 строк за раз.