#awk #sed
Вопрос:
Я хочу на месте отредактировать файл с sed
помощью (Oracle-Linux/Bash).
Содержимое между 2 поисковыми тегами (в форме «#»-комментариев) должно быть закомментировано.
Пример:
Some_Values
#NORMAL_LISTENER_START
LISTENER =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = IPC)
(KEY = LISTENER)
)
)
)
#NORMAL_LISTENER_END
Other_Values
Должно привести к:
Some_Values
#NORMAL_LISTENER_START
# LISTENER =
# (DESCRIPTION =
# (ADDRESS = (PROTOCOL = IPC)
# (KEY = LISTENER)
# )
# )
# )
#NORMAL_LISTENER_END
Other_Values
Следующая команда уже достигает этого, но она также помещает комментарий пробел перед тегами поиска:
sed -i "/#NORMAL_LISTENER_START/,/#NORMAL_LISTENER_END/ s/^/# /" ${my_file}
Теперь мое исследование подсказало мне исключить такие теги поиска, как:
sed -i '/#NORMAL_LISTENER_START/,/#NORMAL_LISTENER_END/{//!p;} s/^/# /' ${my_file}
Но это не сработает — в результате появится следующее сообщение:
sed: -выражение e #1, символ 56: дополнительные символы после команды
Мне нужно, чтобы эти поисковые теги были такими, какие они есть, потому что они мне потом снова понадобятся.
Ответ №1:
Если ed
доступно/приемлемо.
printf '%sn' 'g/#NORMAL_LISTENER_START/ 1;/#NORMAL_LISTENER_END/-1s/^/#/' ,p Q | ed -s file.txt
- Измените
Q
значение наw
, если вы удовлетворены выводом, и произойдет редактирование на месте. - Удалите
,p
, если вы не хотите видеть результат.
Ответ №2:
Это может сработать для вас (GNU sed):
sed '/#NORMAL_LISTENER_START/,/#NORMAL_LISTENER_END/{//!s/^/# /}' file
Используйте диапазон, разделенный двумя регулярными выражениями, и вставляйте #
перед строками между регулярными выражениями, но не включая регулярные выражения.
Альтернатива:
sed '/#NORMAL_LISTENER_START/,/#NORMAL_LISTENER_END/{s/^[^#]/# amp;/}' file
Или, если вы предпочитаете:
sed '/#NORMAL_LISTENER_START/{:a;n;/#NORMAL_LISTENER_END/!s/^/# /;ta}' file
Ответ №3:
Только с показанными вами образцами, пожалуйста, попробуйте выполнить следующий awk
код. Простое объяснение было бы следующим: найдите конкретную строку и установите/снимите значения vars в соответствии с этим, а затем распечатайте обновленные(добавленные # в строках) строки в соответствии с этим, прекратите обновление строк, как только мы найдем строку, из которой нам не нужно обновлять строки.
awk ' /Other_Values/{found=""} found{$0=$0!~/^#/?"#"$0:$0} /Some_Values/{found=1} 1' Input_file
Выше будет выведен вывод на терминале, как только вы будете довольны результатами, вы можете запустить следующий код, чтобы сохранить его в Input_file.
awk ' /Other_Values/{found=""} found{$0=$0!~/^#/?"#"$0:$0} /Some_Values/{found=1} 1' Input_file > temp amp;amp; mv temp Input_file
Пояснение: Добавление подробного объяснения вышеизложенного.
awk ' ##Starting awk program from here.
/Other_Values/{ found="" } ##If line contains Other_Values then nullify found here.
found { $0=$0!~/^#/?"#"$0:$0 } ##If found is SET then check if line already has # then leave it as it is OR add # in starting to it.
/Some_Values/{ found=1 } ##If line contains Some_Values then set found here.
1 ##Printing current line here.
' Input_file ##Mentioning Input_file name here.
Комментарии:
1. Все работает нормально — это немного некрасиво с созданием временного файла. Есть ли способ сделать это без этого?
2. @Dannxy, конечно, в GNU Awk 4.1.0 (выпущен в 2013 году) и более поздних версиях есть возможность редактирования на месте, затем попробуйте выполнить следующее:
gawk -i inplace ' /Other_Values/{found=""} found{$0=$0!~/^#/?"#"$0:$0} /Some_Values/{found=1} 1' Input_file
3. @Dannxy, теперь я также добавил подробное объяснение в свое решение.
4. Похоже, нам придется использовать GNU Awk 4.0.2 — поэтому я должен придерживаться временного файла. Но все в порядке, ты спасла мне день. Спасибо! Приветствую!