Captuerd Text as Variable in Search-Operation

Discussion in 'Perl Misc' started by pk, Jan 12, 2004.

  1. pk

    pk Guest

    Hi!

    If I do a search an have parenthesis in the search string, I've got
    the "captuered" text in the special variables $1, $2 ... My problem
    is: I want to pass the search + replace-text as variables and work
    with the "captured" text (some user enters the search- +
    replace-text); for exampel like that:

    $serach_string = "(.*)XXX(.*);
    $replace_string = "$1---$1";

    $line =~ /$serach_string/;
    $new_line = $replace_string;

    If $line would be aaaXXXbbb , $new_line should be aaa---bbb .

    But I can't use $1 etc. Is there any possibility to get the "captured"
    text?

    pk
    pk, Jan 12, 2004
    #1
    1. Advertising

  2. In article <>,
    pk <> wrote:
    :If I do a search an have parenthesis in the search string, I've got
    :the "captuered" text in the special variables $1, $2 ... My problem
    :is: I want to pass the search + replace-text as variables and work
    :with the "captured" text (some user enters the search- +
    :replace-text); for exampel like that:

    :$serach_string = "(.*)XXX(.*);
    :$replace_string = "$1---$1";

    If the user has control over these expressions, you are going to
    have to be careful, as the user might put in ${text} to cause
    that text to be executed by you.

    :$line =~ /$serach_string/;
    :$new_line = $replace_string;

    :If $line would be aaaXXXbbb , $new_line should be aaa---bbb .

    Not unless the $replace_string were '$1---$2' instead.


    :But I can't use $1 etc. Is there any possibility to get the "captured"
    :text?

    I do not know why you say you cannot use $1 etc. but you do not
    seem to need to.

    $line =~ s/$search_string/$replace_string/;

    But look back to what you had earlier:

    $replace_string = "$1---$1";

    For the code I gave to work, you would instead need to use:

    $replace_string = '$1---$2';

    Notice the single-quotes instead of the double-quotes. When you have
    the double-quotes, the $1 and $2 will be interpolated at the time
    the variable is set. You want the $1 and $2 to be treated literally
    until they are encountered in the context of the s/// .
    --
    Tenser, said the Tensor.
    Tenser, said the Tensor.
    Tension, apprehension,
    And dissension have begun. -- Alfred Bester (tDM)
    Walter Roberson, Jan 12, 2004
    #2
    1. Advertising

  3. pk

    gnari Guest

    "pk" <> wrote in message
    news:...
    >
    > If I do a search an have parenthesis in the search string, I've got
    > the "captuered" text in the special variables $1, $2 ... My problem
    > is: I want to pass the search + replace-text as variables and work
    > with the "captured" text (some user enters the search- +
    > replace-text); for exampel like that:
    >
    > $serach_string = "(.*)XXX(.*);
    > $replace_string = "$1---$1";
    >
    > $line =~ /$serach_string/;
    > $new_line = $replace_string;
    >
    > If $line would be aaaXXXbbb , $new_line should be aaa---bbb .


    actually it would be aaa---aaa

    >
    > But I can't use $1 etc. Is there any possibility to get the "captured"
    > text?


    take a look at the /e modifier of s///
    perdoc perlop
    you can do what you want with /ee
    but you have to think about what you are doing
    s/$serach_string/'"'.$replace_string.'"'/ee;

    you should ABSOLUTELY NOT do this if
    $serach_string is not trusted.

    gnari
    gnari, Jan 12, 2004
    #3
  4. pk

    gnari Guest

    "gnari" <> wrote in message
    news:btupie$jqc$...
    > "pk" <> wrote in message
    > news:...
    > >

    [snipped regexp problem w/ variable replace w/ captures]

    [snipped solution involving /ee]

    I regret having posted the /ee solution.

    here is a solution that is safer:

    $serach_string = '(.*)XXX(.*)';
    $replace_string = '$1---$2';
    $line='aaaXXXbbb';

    my @cap=(undef,/$serach_string/);
    (my $r=$replace_string)=~s/\$(\d)/$cap[$1]/g;
    $line=~s/$serach_string/$r/g;
    gnari, Jan 12, 2004
    #4
  5. pk

    Ben Morrow Guest

    "gnari" <> wrote:
    > here is a solution that is safer:


    You would need to wrap both matches in eval{} to catch the possible
    'Eval-group not allowed at runtime' error.

    > $serach_string = '(.*)XXX(.*)';
    > $replace_string = '$1---$2';
    > $line='aaaXXXbbb';
    >
    > my @cap=(undef,/$serach_string/);


    ITYM my @cap = (undef, $line =~ /$serach_string/);

    > (my $r=$replace_string)=~s/\$(\d)/$cap[$1]/g;


    I would have \d+ here...?

    > $line=~s/$serach_string/$r/g;


    Ben

    --
    And if you wanna make sense / Whatcha looking at me for? (Fiona Apple)
    * *
    Ben Morrow, Jan 12, 2004
    #5
  6. pk

    gnari Guest

    "Ben Morrow" <> wrote in message
    news:btut2v$bi0$...
    >
    > "gnari" <> wrote:
    > > here is a solution that is safer:

    >
    > You would need to wrap both matches in eval{} to catch the possible
    > 'Eval-group not allowed at runtime' error.
    >
    > > $serach_string = '(.*)XXX(.*)';
    > > $replace_string = '$1---$2';
    > > $line='aaaXXXbbb';
    > >
    > > my @cap=(undef,/$serach_string/);

    >
    > ITYM my @cap = (undef, $line =~ /$serach_string/);


    yep. I started with $_ but changed to $line
    to conform with the original post and missed this one

    >
    > > (my $r=$replace_string)=~s/\$(\d)/$cap[$1]/g;

    >
    > I would have \d+ here...?


    I was wondering if someone would mention this :)

    gnari
    gnari, Jan 12, 2004
    #6
  7. pk

    Robin Guest

    > If I do a search an have parenthesis in the search string, I've got
    > the "captuered" text in the special variables $1, $2 ... My problem
    > is: I want to pass the search + replace-text as variables and work
    > with the "captured" text (some user enters the search- +
    > replace-text); for exampel like that:
    >
    > $serach_string = "(.*)XXX(.*);


    for one thing, this doesn't have it's quote at the end...

    > $replace_string = "$1---$1";
    >
    > $line =~ /$serach_string/;
    > $new_line = $replace_string;
    >
    > If $line would be aaaXXXbbb , $new_line should be aaa---bbb .
    >
    > But I can't use $1 etc. Is there any possibility to get the "captured"
    > text?
    >
    > pk


    --
    peace,
    Robin
    --------------

    Please CC a copy of your message to me.
    --------------
    Robin, Jan 13, 2004
    #7
  8. [ posted and accidently mailed also - oops ]

    (pk) writes:

    > If I do a search an have parenthesis in the search string, I've got
    > the "captuered" text in the special variables $1, $2 ... My problem
    > is: I want to pass the search + replace-text as variables and work
    > with the "captured" text (some user enters the search- +
    > replace-text); for exampel like that:
    >
    > $serach_string = "(.*)XXX(.*);
    > $replace_string = "$1---$1";
    >
    > $line =~ /$serach_string/;
    > $new_line = $replace_string;
    >
    > If $line would be aaaXXXbbb , $new_line should be aaa---bbb .
    >
    > But I can't use $1 etc. Is there any possibility to get the "captured"
    > text?


    Y'know, this is the most frequently asked single question not
    currently in the Perl FAQ.

    In some senses it's really just a special case of the existing FAQ
    "How can I expand variables in text strings?" but the s/// question
    actually appears more often the the general case so I think it
    probably warrants its own entry. Anyhow I've always disliked the
    answer given in the FAQ to "How can I expand variables in text
    strings?" because I think it's incomplete.

    Anyhow for more suggestions than you could shake a stick at see dozens
    (hundreds?) previous threads asking the exact same question. Sooner
    or later in any such thread someone is pretty-much sure to mention the
    FAQ "How can I expand variables in text strings?" so searching on that
    phrase should pick up pretty-much all such threads.

    --
    \\ ( )
    . _\\__[oo
    .__/ \\ /\@
    . l___\\
    # ll l\\
    ###LL LL\\
    Brian McCauley, Jan 13, 2004
    #8
  9. pk

    Anno Siegel Guest

    gnari <> wrote in comp.lang.perl.misc:
    > "gnari" <> wrote in message
    > news:btupie$jqc$...
    > > "pk" <> wrote in message
    > > news:...
    > > >

    > [snipped regexp problem w/ variable replace w/ captures]
    >
    > [snipped solution involving /ee]
    >
    > I regret having posted the /ee solution.
    >
    > here is a solution that is safer:
    >
    > $serach_string = '(.*)XXX(.*)';
    > $replace_string = '$1---$2';
    > $line='aaaXXXbbb';
    >
    > my @cap=(undef,/$serach_string/);


    Should be

    my @cap=(undef,$line =~ /$search_string/);

    as has been noted.

    > (my $r=$replace_string)=~s/\$(\d)/$cap[$1]/g;
    > $line=~s/$serach_string/$r/g;


    That does the job, but I find it a little hard to see how it does it.
    This may be more readable:

    # keep whatever the user's pattern captures (to put it back in later)
    my @stick_back_in = $line =~ /$search_string/;

    #do the replacement literally
    $line =~ s/$search_string/$replace_string;

    # now $line has literal "$1", "$2", etc. in it. Replace them
    # one by one with the original text they captured
    $line =~ s/\$\d+/shift @stick_back_in/eg;

    Anno
    Anno Siegel, Jan 13, 2004
    #9
  10. pk

    pk Guest

    "Robin" <> wrote in message news:<btvfeo$chh$>...
    > > If I do a search an have parenthesis in the search string, I've got
    > > the "captuered" text in the special variables $1, $2 ... My problem
    > > is: I want to pass the search + replace-text as variables and work
    > > with the "captured" text (some user enters the search- +
    > > replace-text); for exampel like that:
    > >
    > > $serach_string = "(.*)XXX(.*);

    >
    > for one thing, this doesn't have it's quote at the end...
    >
    > > $replace_string = "$1---$1";
    > >
    > > $line =~ /$serach_string/;
    > > $new_line = $replace_string;
    > >
    > > If $line would be aaaXXXbbb , $new_line should be aaa---bbb .
    > >
    > > But I can't use $1 etc. Is there any possibility to get the "captured"
    > > text?
    > >
    > > pk


    You are right - thanks! But thats not the problem ...

    pk
    pk, Jan 13, 2004
    #10
  11. pk

    pk Guest

    "gnari" <> wrote in message news:<btupie$jqc$>...
    > "pk" <> wrote in message
    > news:...
    > >
    > > If I do a search an have parenthesis in the search string, I've got
    > > the "captuered" text in the special variables $1, $2 ... My problem
    > > is: I want to pass the search + replace-text as variables and work
    > > with the "captured" text (some user enters the search- +
    > > replace-text); for exampel like that:
    > >
    > > $serach_string = "(.*)XXX(.*);
    > > $replace_string = "$1---$1";
    > >
    > > $line =~ /$serach_string/;
    > > $new_line = $replace_string;
    > >
    > > If $line would be aaaXXXbbb , $new_line should be aaa---bbb .

    >
    > actually it would be aaa---aaa
    >
    > >
    > > But I can't use $1 etc. Is there any possibility to get the "captured"
    > > text?

    >
    > take a look at the /e modifier of s///
    > perdoc perlop
    > you can do what you want with /ee
    > but you have to think about what you are doing
    > s/$serach_string/'"'.$replace_string.'"'/ee;
    >
    > you should ABSOLUTELY NOT do this if
    > $serach_string is not trusted.
    >
    > gnari



    Hi gnari,

    thanks a lot !!! This looks like what i've been searching for!

    # These are the arguments on the command-line:
    my $line = $ARGV[0]; # aaaXXXbbb
    my $search = $ARGV[1]; # '(.*)XXX(.*)'
    my $replace = $ARGV[2]; # '$1---$2'

    $line =~ s/$search/'"'.$replace.'"'/ee;

    print "$line\n"; # And this is the result: aaa---bbb
    # exactly what i wanted!

    Solong: pk
    pk, Jan 13, 2004
    #11
  12. pk

    pk Guest

    "gnari" <> wrote in message news:<btuqpt$jtu$>...
    > "gnari" <> wrote in message
    > news:btupie$jqc$...
    > > "pk" <> wrote in message
    > > news:...
    > > >

    > [snipped regexp problem w/ variable replace w/ captures]
    >
    > [snipped solution involving /ee]
    >
    > I regret having posted the /ee solution.
    >
    > here is a solution that is safer:
    >
    > $serach_string = '(.*)XXX(.*)';
    > $replace_string = '$1---$2';
    > $line='aaaXXXbbb';
    >
    > my @cap=(undef,/$serach_string/);
    > (my $r=$replace_string)=~s/\$(\d)/$cap[$1]/g;
    > $line=~s/$serach_string/$r/g;


    Hi gnari,

    thanks again! But this does not work ...

    # These are the arguments on the command-line:
    my $line = $ARGV[0]; # aaaXXXbbb
    my $search = $ARGV[1]; # '(.*)XXX(.*)'
    my $replace = $ARGV[2]; # '$1---$2'


    my @cap=(undef,/$search/);
    (my $r = $replace) =~ s/\$(\d+)/$cap[$1]/g;
    $line =~ s/$search/$r/g;

    print "$line\n";


    # prints out:
    #
    # Use of uninitialized value in pattern match (m//) at ./my_regex_02.pl line 12.
    # Use of uninitialized value in substitution iterator at ./my_regex_02.pl line 14.
    # Use of uninitialized value in substitution iterator at ./my_regex_02.pl line 14.
    # ---

    Solong: pk
    pk, Jan 13, 2004
    #12
  13. pk

    gnari Guest

    "Anno Siegel" <-berlin.de> wrote in message
    news:bu0m2b$g1h$-Berlin.DE...
    > gnari <> wrote in comp.lang.perl.misc:
    > > "gnari" <> wrote in message

    >
    > > (my $r=$replace_string)=~s/\$(\d)/$cap[$1]/g;
    > > $line=~s/$serach_string/$r/g;

    >
    > That does the job, but I find it a little hard to see how it does it.
    > This may be more readable:
    >
    > # keep whatever the user's pattern captures (to put it back in later)
    > my @stick_back_in = $line =~ /$search_string/;
    >
    > #do the replacement literally
    > $line =~ s/$search_string/$replace_string;


    assuming you add the third / of the s///

    >
    > # now $line has literal "$1", "$2", etc. in it. Replace them
    > # one by one with the original text they captured
    > $line =~ s/\$\d+/shift @stick_back_in/eg;


    well, I had thought about that, but what if the original
    $line contains literal $n ?

    gnari
    gnari, Jan 13, 2004
    #13
  14. pk

    pk Guest

    "gnari" <> wrote in message news:<btuqpt$jtu$>...
    > "gnari" <> wrote in message
    > news:btupie$jqc$...
    > > "pk" <> wrote in message
    > > news:...
    > > >

    > [snipped regexp problem w/ variable replace w/ captures]
    >
    > [snipped solution involving /ee]
    >
    > I regret having posted the /ee solution.
    >
    > here is a solution that is safer:
    >
    > $serach_string = '(.*)XXX(.*)';
    > $replace_string = '$1---$2';
    > $line='aaaXXXbbb';
    >
    > my @cap=(undef,/$serach_string/);
    > (my $r=$replace_string)=~s/\$(\d)/$cap[$1]/g;
    > $line=~s/$serach_string/$r/g;




    Hi gnari,

    sorry, my first answer was without that i have already been reading
    the comment to your code. It does the work very well and for me it is
    a good example for the power of Perl (if you know what you are doing).
    What i think i understand is:

    @cap = ( $line =~ /$search/) # $cap[0] is what is found with the
    # first paranthesis; i was already
    # playing around with that for a while;
    # but it took me lots of lines to _not_
    # succeed. Including the 'undef'
    # $cap[0] is not defined. I thing you
    # do this, to have the correct index
    # for $cap[] in the next line
    (my $r=$replace) =~ s/\$(\d+)/$cap[$1]/g; # You search any literal
    # $1, $2 ... (so \d+ makes
    # sense - but this could become quite a
    # monster of regexp ... ) and replace
    # that with the corresponding $cap[].
    # Without the () around '$r=$replace',
    # '$r' holds the number of substituti-
    # ons (right?) but what do the () do ?
    # And: with the (), '$r' already holds,
    # what is later on found on $line ...
    # (at least with the examples, i tried)
    $line =~ s/$search/$r/g; # - so why that third line of code?


    Again, hanks for your help!

    bye: pk
    pk, Jan 13, 2004
    #14
  15. pk

    Ben Morrow Guest

    [comments rearranged somewhat]

    (pk) wrote:
    > What i think i understand is:
    >
    > @cap = (undef, $line =~ /$search/)

    ^^^^^ gnari's undef put back in

    > # $cap[0] is what is found with the first paranthesis; i was already
    > # playing around with that for a while; but it took me lots of lines
    > # to _not_ succeed. Including the 'undef' $cap[0] is not defined. I
    > # thing you do this, to have the correct index for $cap[] in the
    > # next line


    This is right. The expression ($line =~ /$search/) returns a list of
    all the bracketed expressions in the match, the initial 'undef' makes
    sure that the first is in $cap[1] not $cap[0].

    > (my $r=$replace) =~ s/\$(\d+)/$cap[$1]/g;
    > # You search any literal $1, $2 ... (so \d+ makes sense - but this
    > # could become quite a monster of regexp ... )


    This is hardly large :). When regexen get large and nasty, I find it
    really helps to use the /x switch (read perldoc perlre) and to break
    it up into bits in variables (with qr), so I can give them meaningful
    names.

    > # and replace that with the corresponding $cap[].


    > # Without the () around '$r=$replace', '$r' holds the number of
    > # substitutions (right?)


    Yes, that's right. What the brackets do is change the order of
    evaluation, so the statement is equivalent to:

    my $r = $replace;
    $r =~ s/..../g;

    There are some slightly subtle concepts here: (my $r = $replace) is an
    expression (unlike in some other languages), and therefore it has a
    value; the value it has is $r. So the pattern match is then applied to
    that value, and the replacement is done on $r.

    > # but what do the
    > # () do ? And: with the (), '$r' already holds, what is later on
    > # found on $line ... (at least with the examples, i tried)
    >
    > $line =~ s/$search/$r/g; # - so why that third line of code?


    What you failed to try is something like the following:

    $line = "aaa--BBB--";
    $search = "--(.*)--";
    $replace = '==$1==';

    After you execute the code above, $r will be "==BBB==", but $line will
    be "aaa==BBB==".

    Ben

    --
    Like all men in Babylon I have been a proconsul; like all, a slave ... During
    one lunar year, I have been declared invisible; I shrieked and was not heard,
    I stole my bread and was not decapitated.
    ~ ~ Jorge Luis Borges, 'The Babylon Lottery'
    Ben Morrow, Jan 14, 2004
    #15
  16. pk

    Anno Siegel Guest

    gnari <> wrote in comp.lang.perl.misc:
    > "Anno Siegel" <-berlin.de> wrote in message
    > news:bu0m2b$g1h$-Berlin.DE...
    > > gnari <> wrote in comp.lang.perl.misc:
    > > > "gnari" <> wrote in message

    > >
    > > > (my $r=$replace_string)=~s/\$(\d)/$cap[$1]/g;
    > > > $line=~s/$serach_string/$r/g;

    > >
    > > That does the job, but I find it a little hard to see how it does it.
    > > This may be more readable:
    > >
    > > # keep whatever the user's pattern captures (to put it back in later)
    > > my @stick_back_in = $line =~ /$search_string/;
    > >
    > > #do the replacement literally
    > > $line =~ s/$search_string/$replace_string;

    >
    > assuming you add the third / of the s///


    Ugh, where did that go? It was there when I ran the code :)

    > > # now $line has literal "$1", "$2", etc. in it. Replace them
    > > # one by one with the original text they captured
    > > $line =~ s/\$\d+/shift @stick_back_in/eg;

    >
    > well, I had thought about that, but what if the original
    > $line contains literal $n ?


    ....or if the replacement introduces them? Then it goes wrong, but
    so does yours in a quick test. The OP didn't seem overly concerned
    about this kind of robustness, so I thought, why bring it up? :)

    Anno
    Anno Siegel, Jan 14, 2004
    #16
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. david ullua
    Replies:
    13
    Views:
    646
  2. Replies:
    1
    Views:
    332
  3. raan
    Replies:
    2
    Views:
    439
  4. Buzz Lightyear
    Replies:
    10
    Views:
    1,105
    Alexander Bartolich
    Aug 12, 2009
  5. Abby Lee
    Replies:
    5
    Views:
    378
    Abby Lee
    Aug 2, 2004
Loading...

Share This Page