Как мне игнорировать совпадение регулярных выражений, если строка имеет специальный префикс?

#regex #perl

#регулярное выражение #perl

Вопрос:

Я использую это регулярное выражение в Perl для сопоставления и замены следующих выражений:

  • _HI2_
  • _HI_2
  • HI2_
  • _HI_2

     if ($subject =~ m/_?HI2?_?|HI2?_?/) {
        # Successful match
    } else {
        # Match attempt failed
    }
      

Я также хочу сделать это, хотя:

 The text is:   ABCDEMAFGHIJ
  

Это последовательность HI там, но ее следует игнорировать, потому что, если вы посмотрите налево, вы увидите, что эта строка начинается с The text is: .

 The text is:   ABCDEHI2FGHI
  

Как и выше, здесь две последовательности HI .

Как я могу встроить в это регулярное выражение совпадение и игнорировать его из-за префикса строки?

Ответ №1:

Почему бы просто не сопоставить дважды? Если $subject не соответствует /^тексту:/ , запустите замену ..

Комментарии:

1. Просто используйте if(){}else{} . Предлагаю вам попробовать что-нибудь прочитать.. может быть, «современный perl»? Это бесплатно в формате PDF здесь: onyxneon.com/books/modern_perl

Ответ №2:

Попробуйте это регулярное выражение:

 /^(?!The text is:).*(?:_?HI2?_?|HI2?_?)/
  

Или используйте два совпадения, например:

 if($subject !~ /^This text is:/i amp;amp; $subject =~ /_?HI2?_?|HI2?_?/)
  

Комментарии:

1. используя пример 1: AAA_HI2_BBB_CCC <— Этот, кажется, единственный, который распознается, и он также распознает AAA_ перед HI2_ AAA_HI_2_BBB_CCC Текст: ABCDEMAFGHIJ Текст: ABCDEHI2FGHI

Ответ №3:

Я только что обнаружил этот замечательный ресурс здесь и раздел о Perl.

Вы можете найти там детали (*SKIP)(*F) конструкции, которая поразит вас; вы описали проблему как однострочную:

 cat > test.txt <<EOF
_HI2_
_HI_2xxxHI_2
The text is:   ABCDEMAFGHIJ
HI2_
The text is:   ABCDEHI2FGHI
_HI_2
EOF

perl -ne '/^The text is:.*$(*SKIP)(*F)|. / amp;amp; s/_?HI_?2?_?/HAPPY/; print' test.txt

# or

perl -ne 's/(^The text is:.*$)(*SKIP)(*F)|_?HI_?2?_?/HAPPY/g; print' test.txt
  

Я вновь обрел любовь и уважение к Perl; Я предпочитаю Sed, но теперь я знаю, как пропускать строки (читай: оставлять без изменений) в Perl, я буду меньше колебаться

Ответ №4:

Попробуйте указать, что это начало строки с «^», игнорируйте пробелы, если это, по вашему мнению, необходимо (я всегда стараюсь это делать). Также вы могли бы пометить конец строки символом «$»

 if ($subject =~ m/^s*_?HI2?_?|HI2?_?/) {
    # Successful match
} else {
    # Match attempt failed
}
  

Ответ №5:

Не самый элегантный метод, но простой для понимания (TIMTOWTDI 🙂

 #!/usr/bin/perl

use strict;
use warnings;


my @text = ("ABCDEHI2FGHI", "The text is:   ABCDEHI2FGHI");

for (@text) {
    my $new = my_replace($_); # do the replacement
    print "$newn";           # print result
}

sub my_replace {
    my ($text) = @_;
    return $text if ($text =~ m/The text is:/);      # return if prefixed / no replacement
    $text =~ s/(_?HI2?_?|HI2?_?)/__replacement__/g;  # do replace (give a replacement string here)
    return $text;                                    # return result of replacement
}

  

В противном случае вы можете использовать «отрицательный взгляд назад«.

Чтобы попробовать, смотрите regex101 или debuggex.

Ответ №6:

/(?<!^The text is.*)(_?HI2?_?|HI2?_?)/

Комментарии:

1. Ссылки могут быть только фиксированной длины

2. хммм, строки с приветом в начале и «Текст есть» в них, похоже, все еще подбираются?

3. было бы лучше просто позволить perl-коду делать это? if ($subject =~ m/The text is/) { # ignore the line, move onto the next line? -- what would the perl code be to do that? } else { # Match attempt failed }