Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

Hi monks

I am using the following to perform substitutions in a text:

    $text =~     s/\'t/ \'t/g;

It basically adds a white space before 't. Now I want to add some exceptions to this matching rules: with "aren't" and "isn't" the regex shouldn't match, in all other cases yes. It is possible to achieve this?

Replies are listed 'Best First'.
Re: substitution with exceptions
by LanX (Saint) on Sep 27, 2018 at 19:17 UTC
    Looks like you want a Negative Lookbehind Assertion:

    (?<!foo) Negative Lookbehind Asserts that what immediately precedes the current position in the string is not foo

    update

    maybe try s/(?<!\bisn)(?<!\baren)'t/ 't/g

    \b ensures a word boundary.

    (actually in order to play save you should also check for a trailing boundary 't\b

    Cheers Rolf
    (addicted to the Perl Programming Language :)
    Wikisyntax for the Monastery FootballPerl is like chess, only without the dice

      Negative look-behind only works for fixed length patterns, "aren" and "isn" are of different lengths.
      (?<!n)'t
      might work, but if you need to exclude both, you can't use
      (?<!aren|isn)'t Variable length lookbehind not implemented in regex m/(?<!aren|isn)'t/
      You can specify them one by one, though:
      (?<!aren)(?<!isn)'t
      ($q=q:Sq=~/;[c](.)(.)/;chr(-||-|5+lengthSq)`"S|oS2"`map{chr |+ord }map{substrSq`S_+|`|}3E|-|`7**2-3:)=~y+S|`+$1,++print+eval$q,q,a,
        Tsk, you replied to the king of updates without checking ?

        ;-p

        Cheers Rolf
        (addicted to the Perl Programming Language :)
        Wikisyntax for the Monastery FootballPerl is like chess, only without the dice

      WOW. It works perfectly.

Re: substitution with exceptions
by AnomalousMonk (Archbishop) on Sep 27, 2018 at 21:40 UTC

    Perhaps a bit more fancy than necessary, but a lot is factored out. Needs Perl version 5.10+ for  (*SKIP) (*FAIL) (see Special Backtracking Control Verbs in perlre):

    c:\@Work\Perl\monks>perl -wMstrict -le "use 5.010; ;; my $text = q{x aren't y ain't z isn't w won't u 't v daren't t}; print qq{'$text'}; ;; my $sq_t = qr{ 't }xms; my $skip_sq_t = qr{ aren | isn }xms; ;; my $exceptions_sq_t = qr{ \b $skip_sq_t $sq_t (*SKIP) (*FAIL) }xms; ;; $text =~ s{ $exceptions_sq_t? (?<= [[:alpha:]]) (?= $sq_t) }{ }xmsg; print qq{'$text'}; " 'x aren't y ain't z isn't w won't u 't v daren't t' 'x aren't y ain 't z isn't w won 't u 't v daren 't t'

    Update: Another, more highly factored approach. See haukex's article Building Regex Alternations Dynamically for more info on how the  $exception_n_sq_t regex is built. Something like this could be used to manufacture countless target/exception regex pairs.

    c:\@Work\Perl\monks>perl -wMstrict -le "use 5.010; ;; my $sq_t = qr{ 't }xms; ;; my $target_n_sq_t = qr{ (?<= [[:alpha:]]) (?= $sq_t) }xms; ;; my ($exception_n_sq_t) = map qr{ \b (?: $_) n $sq_t (*SKIP) (*FAIL) }xms, join q{ | }, qw(are is) ; print $exception_n_sq_t; ;; my $text = q{x aren't y ain't z isn't w won't u 't v daren't t}; print qq{'$text'}; ;; $text =~ s{ $exception_n_sq_t? $target_n_sq_t }{ }xmsg; print qq{'$text'}; " (?msx-i: \b (?: are | is) n (?msx-i: 't ) (*SKIP) (*FAIL) ) 'x aren't y ain't z isn't w won't u 't v daren't t' 'x aren't y ain 't z isn't w won 't u 't v daren 't t'


    Give a man a fish:  <%-{-{-{-<