in reply to Regex stored in a scalar

A regex should be between / / marks, so something like this:
$line =~ /$regex/;
but that won't work either in your case, because:
s/\),\(/\)\n\(/
is a substitution operator, it is not a regex. Only the part between the first two slashes is a regex, not the rest.

So if you want to make substitutions you probably want to capture two inputs from the user or from the command line, the searched pattern and the substitution (not tested).

my $regex = <STDIN>; chomp $regex; my $subst = <STDIN>; chomp $subst; while (<INPUTFILE>) { my $line = $_; s/$regex/$subst/gi; }
And for a big file, you might want to add the o modifier, it may be faster (but that may depend on your version of Perl).

Update: Oh, BTW, if you're used to do it in vi, you might consider sed. You should feel at home.

Update 2: I crossed out the first part of my answer, as it was at least very incomplete, as kindly pointed out by AnomalousMonk. Only the second part was really relevant to the OP problem.

Replies are listed 'Best First'.
Re^2: Regex stored in a scalar
by kroach (Pilgrim) on Aug 22, 2015 at 10:49 UTC
    It would be better to quote the pattern with qr// rather than using /o. Like this:
    $regex = qr/$regex/
      Yes, you're probably right, ++, this was just a quick additional note for speed, not much to to with the OP question.
Re^2: Regex stored in a scalar
by AnomalousMonk (Archbishop) on Aug 22, 2015 at 14:34 UTC
    A regex should be between / / marks ...

    The  =~ operator is sufficiently DWIMic that it will take any string as a regex. It will even take all the  qr// regex modifiers if they are embedded as  (?adlupimsx-imsx) extended patterns.

    c:\@Work\Perl>perl -wMstrict -le "my $regex = '(?xms) ((.) \2{2,})'; ;; for my $s (qw(aeiou aeeiou aeiiiou aeioooou)) { print qq{match: captured '$1'} if $s =~ $regex; } " match: captured 'iii' match: captured 'oooo'

    ... but that won't work ...

    The first comment I made is actually rather trivial in the face of your second point; the substitution  s/\),\(/\)\n\(/ is, indeed, a substitution and not a regex — and bang, the whole endeavor hits a brick wall.


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

      Yes, AnomalousMonk, you are right ++, and I actually knew that what I was saying was not quite right, not that I was thinking to you said in your comments, but I was thinking that you can have a regex in the form:
      if (m{pattern}) { # ...
      or many other delimiter pairs. I really wanted to get that point out of the way quickly to get to the real thing about the substitution not being a regex, so that I was a bit negligent in the way I wrote that first part.

      You're absolutely right, the first part of my comment stood for correction.

Re^2: Regex stored in a scalar
by girarde (Hermit) on Aug 22, 2015 at 14:33 UTC
    sed would likely be wicked fast for this, too.
      It depends on the quality of the sed implementation (and also the Perl version). I have seen cases where Perl was 2 to 5 times faster than either sed or awk (I don't remember for sure from which vendor), although this was more than 10 years ago. In the more recent tests I made (but with rather old OS), there was no significant difference and it would also depend on the complexity of the processing being applied.

      I think that, in general, tests are required to decide the best way to go (if it matters at all, e.g. if your files to be processed are really so large that it will make a significant difference for you).

Re^2: Regex stored in a scalar
by itsscott (Sexton) on Aug 25, 2015 at 02:53 UTC

    I do like your sed suggestion. I have a snippet I've used for 20 years to either process 1 or many files, and it's fast and low load. I've changed 10's of thousands of files on a server in mear moments (after extensive testing of course!! to save restoring)

    This command will find and replace the string 'old' with 'new' in all files with the htm/html extension recursively from where you run the command. be careful, there's no undo! Use your regex as usual. Hopefully someone will find this snippet useful, I sure have 1000's of times!

    find . -name '*.htm*' -type f | xargs sed -i 's/old/new/g'
Re^2: Regex stored in a scalar
by poj (Abbot) on Aug 22, 2015 at 16:35 UTC

    The OP has )\n( as the substition. I can't see how to enter that with my $subst = <STDIN>;
    poj

      True, it won't work this way, but this quick test under the Perl debugger show that it might be feasible with a slight syntax tweak and one further step to process it. Here, I am passing the replacement string with \n to my debugger session:
      $ perl -de 42 foo\\n Loading DB routines from perl5db.pl version 1.33 Editor support available. Enter h or `h h' for help, or `man perldebug' for more help. main::(-e:1): 42 DB<1> $c = shift; DB<2> x $c 0 'foo\\n' DB<3> $c =~ s|\\n|\n|; DB<4> x $c 0 'foo ' DB<5>
      So, this seems to work, although it might not be the most elegant construct. Of course, it also assumes that you know when writing your program beforehand, you might need some newline characters to be reprocessed.
        I can't see how to enter that with my $subst = <STDIN>;
        True, it won't work this way ... it might be feasible with a slight syntax tweak and one further step to process it ... assumes that you know ... you might need some newline characters to be reprocessed

        As long as you can get  \nything into a scalar, you can search/replace with it, and a statement like
            my $subst = <STDIN>;
        is perfectly adequate to capture any sequence with a literal backslash in it:

        c:\@Work\Perl>perl -wMstrict -e "print 'enter a string: '; my $string = <STDIN>; chomp $string; print qq{'$string' \n}; " enter a string: )\n( ')\n('
        (Caveat: Actually, I can only test this under Windoze; there may be OSen that mung backslashes in situations like this.)

        Once you have captured a string with a backslash, you can use it for search/replace straightforwardly:

        c:\@Work\Perl>perl -wMstrict -le "printf 'enter search regex: '; my $search = <STDIN>; chomp $search; ;; printf 'enter replacement string: '; my $replace = <STDIN>; chomp $replace; ;; print qq{doing s/$search/$replace/}; ;; my $s = qq{as\ngh\njk}; printf qq{%*s: '$s' \n}, 7, 'initial'; ;; my @regex = ( { lh => $search, rh => $replace, }, ); ;; for my $hr_s (@regex) { $s =~ s[ (?-x)$hr_s->{lh}]{ qq{qq{$hr_s->{rh}}} }xmsgee; } ;; printf qq{%*s: '$s' \n}, 7, 'final'; " enter search regex: \n enter replacement string: __\n__ doing s/\n/__\n__/ initial: 'as gh jk' final: 'as__ __gh__ __jk'
        (This is essentially the example code from below.)


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