http://qs321.pair.com?node_id=869247

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

Hello again everyone, Sorry about being so cryptic but I will put my question in code. I found a way to do what I want but it seems so cumbersome. I am sure a better way exist. well here is the code
open(XFIL,"var.txt") || die $!; @main = <XFIL>; close(XFIL); open(XFIL,">var.txt") || die $!; foreach $line (@main) { $line =~ s/\n/replace/g; print XFIL $line; } close(XFIL); open(XFIL,"var.txt") || die $!; @main = <XFIL>; close(XFIL); open(XFIL,">var.txt") || die $!; foreach $line (@main) { $line =~ s/the line to be replaced/this is the new line/; $line =~ s/replace/\n/g; print XFIL $line; } close(XFIL);
Hello , I have a quick question . Lets say the word data is in the $string 20 times. I want to only match the first instance of the word data . How would I do this ?
if ($string =~ m/data/) { do whatever }

Replies are listed 'Best First'.
Re: search one instance
by roboticus (Chancellor) on Nov 03, 2010 at 14:58 UTC

    toniax:

    That should work ... what's the problem with it? After all, once it finds "data", what incentive is there for it to keep searching?

    Update: If you're looking for the location of the string, you may be interested in perldoc -f index

    ...roboticus

Re: search one instance
by d5e5 (Beadle) on Nov 03, 2010 at 15:08 UTC
    I'm not sure I understand your question, but why not the following?
    #!/usr/bin/perl use strict; use warnings; my $string = 'data' x 20; if ($string =~ m/data/) { print "Matching '$&'", "\n"; } print 'from $string which has value of ', "$string\n"; #Output: #Matching 'data' #from $string which has value of datadatadatadatadatadatadatadatadatad +atadatadatadatadatadatadatadatadatadatadata
Re: search one instance
by eff_i_g (Curate) on Nov 03, 2010 at 15:47 UTC
    There's the ?PATTERN? syntax. Per Regexp Quote Like Operators:
    ?PATTERN? This is just like the /pattern/ search, except that it matches only on +ce between calls to the reset() operator. This is a useful optimizati +on when you want to see only the first occurrence of something in eac +h file of a set of files, for instance.
Re: search one instance
by suhailck (Friar) on Nov 03, 2010 at 15:03 UTC
    m/^.*?(data)/

    An example

    perl -le '$_="abc"."data" x 5;print; print "position of first data : ",pos while m/^.*?(?=data)/g;' abcdatadatadatadatadata position of first data : 3
      when I tried your example, it reported the position of the last "data", not the first.

      I, also, cannot figure out how you get a position of 3 from the given code.

        Sorry, i missed out a question mark "?" in m/^.*?(?=data)/

        Thanks for noticing that :)
        Updated the code above...
Re: search one instance
by AnomalousMonk (Archbishop) on Nov 03, 2010 at 19:38 UTC

    I don't quite understand how we get from toniax's OP to finding all starting positions of the substring, but here's another way:

    >perl -wMstrict -le "my $str = qq{foo data } x 5; print $str; ;; print qq{start of 'data' at $-[1]} while $str =~ m{ (data) }xmsg; " foo data foo data foo data foo data foo data start of 'data' at 4 start of 'data' at 13 start of 'data' at 22 start of 'data' at 31 start of 'data' at 40

    See @- (and its cousin @+) in perlvar.

Re: search one instance
by d5e5 (Beadle) on Nov 04, 2010 at 20:34 UTC
    toniax: In response to your revised question, instead of your script to read a file and replace only the first line that matches your pattern I would use in-place editing, read and print each line and update a variable when the I've found and replaced the first occurrence of the pattern.
    #!/usr/bin/perl use strict; use warnings; my $filename = '/home/david/Programming/Perl/data/var.txt'; #So you can use diamond operator and inplace editing push @ARGV, $filename; #Enable inplace editing. Copy of input file saved as 'var.txt.bk' $^I = ".bk"; my $replaced = 0; while(<>){ chomp; if ($replaced == 0 and s/the line to be replaced/this is the new line/){ $replaced++; } print "$_\n"; }
A reply falls below the community's threshold of quality. You may see it by logging in.