sed: как удалить диапазон строк в файле, ограниченный строками комментариев? - PullRequest
0 голосов
/ 09 мая 2020

Пример файла:

##
# Host Database
#
# localhost is used to configure the loopback interface
# when the system is booting.  Do not change this entry.
##
127.0.0.1   localhost
255.255.255.255 broadcasthost
::1             localhost
# Added by Docker Desktop
# To allow the same kube context to work on the host and the container:
127.0.0.1 kubernetes.docker.internal
# End of section
# <docker-registry>
docker.local 127.0.0.1
# </docker-registry>

Используя функцию выражения диапазона sed (https://unix.stackexchange.com/a/236754), я хотел бы удалить следующие строки:

# <docker-registry>
docker.local 127.0.0.1
# </docker-registry>

После дюжины попыток с разными синтаксисами это лучшее, что я мог придумать:

sed -n 's|# <docker-registry>|,|# </docker-registry>|p' $FILE

Без флага s я получаю следующую ошибку:

sed: 1: "|# <docker-registry>|,| ...": invalid command code |

С флагом s я получаю следующую ошибку:

sed: 1: "s|# <docker-registry>|, ...": bad flag in substitute command: '#'

Как добиться желаемого результата?

Ответы [ 2 ]

1 голос
/ 09 мая 2020

Вы получите результат на стандартный вывод:

sed -e '/# <docker-registry>/,/# <\/docker-registry>/d' yourdatafile

Если вам нужно отредактировать файл данных, используйте ed вместо sed. Не используйте перенаправление к файлу, из которого вы читаете, так как это может повредить файл.

Ed script:

/# <docker-registry>/,/# <\/docker-registry>/d
w
q

call:

ed yourdatafile <script.ed
0 голосов
/ 09 мая 2020

TL; DR:

sed '/# <docker-registry>/,/# <\/docker-registry>/d' $FILE > "$FILE.tmp"
mv "$FILE.tmp" $FILE

ОБЪЯСНЕНИЕ:

Я нашел ответ, когда отправлял вопрос, поэтому для потомков :

  1. Чтобы удалить строки из вывода sed, добавьте флаг d в конце выражения:

sed -n 's|# <docker-registry>|,|# </docker-registry>|d' $FILE

sed создает потоки. Чтобы перезаписать файл, передайте результат в файл:

sed -n 's|# <docker-registry>|,|# </docker-registry>|d' $FILE > $FILE

Ошибки sed: 1: "s|# <docker-registry>|, ...": bad flag in substitute command: '#' можно избежать, используя разделитель по умолчанию и экранируя / в конце шаблона:

sed '/# <docker-registry>/,/# <\/docker-registry>/d' $FILE > $FILE

По какой-то причине приведенная выше команда в (3) стирает исходный файл и не передает туда новое содержимое. Печать в новый файл с последующим перемещением его поверх старого дает результат:
sed '/# <docker-registry>/,/# <\/docker-registry>/d' $FILE > "$FILE.tmp"
mv "$FILE.tmp" $FILE

Не стесняйтесь редактировать, если у вас есть более элегантный ответ:)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...