Как закомментировать несколько строк, соответствующих регулярному выражению, используя sed или awk

у меня есть файл, который содержит этот:

[...]

location /static {
    ...
    multiple lines
    ...
}

[...]

location /static/ {
    ...
    multiple lines
    ...
}

[...]

и я хочу к вам:

[...]

# location /static {
#     ...
#     multiple lines
#     ...
# }

[...]

# location /static/ {
#     ...
#     multiple lines
#     ...
# }

[...]

Как я могу это сделать, отдав свой файл команде unix?

10
задан Natim
04.02.2023 16:48 Количество просмотров материала 3134
Распечатать страницу

2 ответа

это не тривиально. Если можно считать, что каждый {} блок не содержит других вложенных {} блоки легче и вы можете сделать что-то вроде этого:

perl -pe 'if(/location\s*\/static/){$n=1}elsif(/}/){$n=0} s/^/#/ if $n==1;' file

это просто наборы $n to 1 если текущая строка соответствует location /static и устанавливает его обратно к 0 в первом } после location/static. Затем, пока $n==1, это addas a # к началу строки. The -p флаг причиняет perl автоматически закрепить петлей через введите файл и распечатайте каждую строку.

теперь, если вы можете иметь произвольную глубину вложенных блоков в блоках, которые вы хотите прокомментировать, все становится сложнее. Например, если у вас есть что-то вроде этого:

location /static {
   if(foo){
      print "one";
   }
   elsif(bar){
      print "two";
   }
}

для подобных случаев, простое решение выше потерпит неудачу, и вам придется использовать тот, который отслеживает количество открытых {. Например (это на самом деле однострочный, вы можете скопировать / вставить прямо в свой терминал, я просто расширил его для clarity):

perl -pe 'if(/location\s*\/static/){$n=1;}
          elsif(/}/ && $open==0){$n=0} 
          if($n==1 && /{/){$open++} ## count open brackets
          elsif($n==1 && /}/){$open--} ## count closing brackets
          if($n==1 && $open>0){ s/^/#/}; ' file

наконец, если решения работают должным образом, вы можете добавить -i флаг сделайте изменения в самом файле:

perl -i -pe 'if(/location\s*\/static/){$n=1}elsif(/}/){$n=0} s/^/#/ if $n==1;' file
2
отвечен terdon 2023-02-06 00:36

извлечение (возможно вложенных) блоков с разделителями регулярными выражениями не особенно весело или легко. Тем не менее, есть элегантное решение, используя модуль, который уже давно поставляется с Perl (так как Perl был одним из ваших тегов), а именно. Текст::Балансный:

#!/usr/bin/env perl
use strict;
use warnings;
use Text::Balanced qw( extract_bracketed );

my $in = do { local $/ = undef; <> };
while( $in ) {
    my $out;
    if    ( $in =~ s/^(location\s+\S+\s+)// ) { ( $out =  . extract_bracketed($in) ) =~ s/^/# /mg }
    elsif ( $in =~ s/^(.*[\r\n]*)// )         { $out =  }
    print $out;
}

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

  • если ведущий часть содержит location ключевое слово, за которым следует пробел (\s+), и что-то, что выглядит так, как будто это может быть идентификатор (в настоящее время он очень грубо идентифицируется как последовательность символов без пробелов,\S+), то extract_bracketed извлечет следующий блок с разделителями (по умолчанию он извлекает блок, разделенный любой из следующих пар:[],{},() или <>). extract_bracketed будет корректно работать с вложенными, сбалансированными разделителями внутри блока извлеченный. Следующая подмена s/^/# /mg отвечает за комментирование отдельных строк в блоке, независимо от того, сколько строк он может содержать. Затем блок (вместе с ведущим ключевым словом location) распечатывается.

  • в противном случае строка (вплоть до символа новой строки) извлекается и печатается без изменений.

некоторые другие вещи, чтобы Примечание:

  1. текст прочитан и сохранен в своем целиком в строку ($in) путем определения разделителя записей $/
  2. - специальная переменная, содержащая содержимое регулярного выражения, разделенное круглыми скобками; например, for (location\s+\S+\s+), $1 содержит текст location /static (включая пробелы).
0
отвечен Edward 2023-02-06 02:53

Постоянная ссылка на данную страницу: [ Скопировать ссылку | Сгенерировать QR-код ]

Ваш ответ

Опубликуйте как Гость или авторизуйтесь

Имя
Вверх