FAQ
Recently, I was asked to find the first occurrence of a word in a text file and replace it with an alternate word.  This was my solution.  As a new Perl programmer, I feel like this solution was too C like and not enough Perl like.  So, my question is what would have been the Perl like solution to this problem?


In this example there is little risk of running out of memory reading the file.  But had this been a production environment or an unknown file size, I would have had to consider that.


#!/usr/bin/perl
use strict;
use warnings;

#program finds the first occurrence of the word Dood and
#replaces it with the word Dude in the file data.txt.

open FP, "+<", "data.txt" || die "Cant open data.txt " . $!;

my @buffer = <FP>;
seek FP,0,0;
my $do_replace = 1; #used to control replacing in multiline files.
my $line;
my $data;
foreach $data (@buffer)
{
if ($do_replace == 1)
{
$line = $data;
$data =~ s/Dood/Dude/;
if ($line ne $data)
{
$do_replace = 0; #we did a substitution so do no more.
}
}
print FP $data;
}
close FP;

#Test data
#Dude! Where's my car?
#Dood! Where's my car?
#Dood! Where's my car?



--
Ronald Weidner

Search Discussions

  • Shawn H Corey at Aug 21, 2011 at 11:52 am

    On 11-08-21 07:33 AM, Ron Weidner wrote:
    Recently, I was asked to find the first occurrence of a word in a text file and replace it with an alternate word. This was my solution. As a new Perl programmer, I feel like this solution was too C like and not enough Perl like. So, my question is what would have been the Perl like solution to this problem?
    IO::Insitu http://search.cpan.org/~dconway/IO-InSitu-0.0.2/lib/IO/InSitu.pm


    --
    Just my 0.00000002 million dollars worth,
    Shawn

    Confusion is the first step of understanding.

    Programming is as much about organization and communication
    as it is about coding.

    The secret to great software: Fail early & often.

    Eliminate software piracy: use only FLOSS.

    "Make something worthwhile." -- Dear Hunter
  • Uri Guttman at Aug 21, 2011 at 2:10 pm
    "SHC" == Shawn H Corey writes:
    SHC> On 11-08-21 07:33 AM, Ron Weidner wrote:
    Recently, I was asked to find the first occurrence of a word in a text file and replace it with an alternate word. This was my solution. As a new Perl programmer, I feel like this solution was too C like and not enough Perl like. So, my question is what would have been the Perl like solution to this problem?
    >>

    SHC> IO::Insitu http://search.cpan.org/~dconway/IO-InSitu-0.0.2/lib/IO/InSitu.pm

    even simpler is File::Slurp::edit_file

    uri

    --
    Uri Guttman -- uri AT perlhunter DOT com --- http://www.perlhunter.com --
    ------------ Perl Developer Recruiting and Placement Services -------------
    ----- Perl Code Review, Architecture, Development, Training, Support -------
  • Rob Dixon at Aug 21, 2011 at 12:25 pm

    On 21/08/2011 12:33, Ron Weidner wrote:
    Recently, I was asked to find the first occurrence of a word in a
    text file and replace it with an alternate word. This was my
    solution. As a new Perl programmer, I feel like this solution was too
    C like and not enough Perl like. So, my question is what would have
    been the Perl like solution to this problem?

    In this example there is little risk of running out of memory
    reading the file. But had this been a production environment or an
    unknown file size, I would have had to consider that.


    #!/usr/bin/perl
    use strict;
    use warnings;

    #program finds the first occurrence of the word Dood and
    #replaces it with the word Dude in the file data.txt.

    open FP, "+<", "data.txt" || die "Cant open data.txt " . $!;

    my @buffer =<FP>;
    seek FP,0,0;
    my $do_replace = 1; #used to control replacing in multiline files.
    my $line;
    my $data;
    foreach $data (@buffer)
    {
    if ($do_replace == 1)
    {
    $line = $data;
    $data =~ s/Dood/Dude/;
    if ($line ne $data)
    {
    $do_replace = 0; #we did a substitution so do no more.
    }
    }
    print FP $data;
    }
    close FP;

    #Test data
    #Dude! Where's my car?
    #Dood! Where's my car?
    #Dood! Where's my car?
    Hey Ronald

    Here is a program like yours, that reads the entire file into memory and
    then outputs the altered version.

    #!/usr/bin/perl
    use strict;
    use warnings;

    #program finds the first occurrence of the word Dood and
    #replaces it with the word Dude in the file data.txt.

    open my $fp, "<", "data.txt" or die "Cant open data.txt for input: $!";
    my @buffer = <$fp>;

    open my $fp, ">", "data.txt" or die "Cant open data.txt for output: $!";
    my $replaced;

    foreach my $line (@buffer) {
    unless ($replaced) {
    $replaced++ if $line =~ s/Dood/Dude/;
    }
    }
    __END__

    But if you may be working with large files and have to be careful with
    memory, it is best to process the input file one line at a time. There
    are special built-in ways of doing this sort of thing, but it is best
    for now to write something that is clear and straightforward. Something
    like this perhaps.

    #!/usr/bin/perl
    use strict;
    use warnings;

    #program finds the first occurrence of the word Dood and
    #replaces it with the word Dude in the file data.txt.

    rename 'data.txt', 'data.old' or die "Rename of input file failed: $!";
    open my $in, '<', 'data.old' or die "Failed to open input file: $!";
    open my $out, '>', 'data.txt' or die "Failed to open output file: $!";

    my $replaced;
    while (my $line = <$in>) {
    unless ($replaced) {
    $replaced++ if $line =~ s/Dood/Dude/;
    }
    print $out $line;
    }
    __END__


    I hope this helps,

    Rob
  • Rob Dixon at Aug 21, 2011 at 12:31 pm

    On 21/08/2011 13:21, Rob Dixon wrote:
    Hey Ronald

    Here is a program like yours, that reads the entire file into memory and
    then outputs the altered version.

    #!/usr/bin/perl
    use strict;
    use warnings;

    #program finds the first occurrence of the word Dood and
    #replaces it with the word Dude in the file data.txt.

    open my $fp, "<", "data.txt" or die "Cant open data.txt for input: $!";
    my @buffer =<$fp>;

    open my $fp, ">", "data.txt" or die "Cant open data.txt for output: $!";
    my $replaced;

    foreach my $line (@buffer) {
    unless ($replaced) {
    $replaced++ if $line =~ s/Dood/Dude/;
    }
    }
    __END__
    I'm sorry - that wasn't the version I tested! Here is the correct
    working program. The second program I posted works fine.

    Rob

    #!/usr/bin/perl
    use strict;
    use warnings;

    #program finds the first occurrence of the word Dood and
    #replaces it with the word Dude in the file data.txt.

    my $fp;
    open $fp, "<", "data.txt" or die "Cant open data.txt for input: $!";
    my @buffer = <$fp>;

    open $fp, ">", "data.txt" or die "Cant open data.txt for output: $!";
    my $replaced;

    foreach my $line (@buffer) {
    if (not $replaced) {
    $replaced++ if $line =~ s/Dood/Dude/;
    }
    print $fp $line;
    }
    __END__
  • John W. Krahn at Aug 21, 2011 at 11:09 pm

    Ron Weidner wrote:
    Recently, I was asked to find the first occurrence of a word in a text
    file and replace it with an alternate word. This was my solution. As
    a new Perl programmer, I feel like this solution was too C like and
    not enough Perl like. So, my question is what would have been the
    Perl like solution to this problem?


    In this example there is little risk of running out of memory reading
    the file. But had this been a production environment or an unknown
    file size, I would have had to consider that.


    #!/usr/bin/perl
    use strict;
    use warnings;

    #program finds the first occurrence of the word Dood and
    #replaces it with the word Dude in the file data.txt.

    open FP, "+<", "data.txt" || die "Cant open data.txt " . $!;

    my @buffer =<FP>;
    seek FP,0,0;
    my $do_replace = 1; #used to control replacing in multiline files.
    my $line;
    my $data;
    foreach $data (@buffer)
    {
    if ($do_replace == 1)
    {
    $line = $data;
    $data =~ s/Dood/Dude/;
    if ($line ne $data)
    {
    $do_replace = 0; #we did a substitution so do no more.
    }
    }
    print FP $data;
    }
    close FP;

    #Test data
    #Dude! Where's my car?
    #Dood! Where's my car?
    #Dood! Where's my car?
    There are a few ways to do what you require:

    #!/usr/bin/perl
    use strict;
    use warnings;
    use Tie::File

    tie my @buffer, 'Tie::File', 'data.txt' or die "Cant open data.txt $!";

    for ( @buffer ) {
    s/Dood/Dude/ and last;
    }

    __END__


    #!/usr/bin/perl
    use strict;
    use warnings;

    local ( $^I, @ARGV ) = ( '', 'data.txt' );

    while ( <> ) {
    ?Dood? && s/Dood/Dude/;
    print;
    }

    __END__


    #!/usr/bin/perl
    use strict;
    use warnings;
    use Fcntl ':seek';

    open my $FP, '+<', 'data.txt' or die "Cant open data.txt $!";
    read $FP, my $buffer, -s $FP or die "Cant read from data.txt $!";
    seek $FP, 0, SEEK_SET or die "Cant seek on data.txt $!";
    $buffer =~ s/Dood/Dude/;
    print $FP $buffer;

    __END__



    John
    --
    Any intelligent fool can make things bigger and
    more complex... It takes a touch of genius -
    and a lot of courage to move in the opposite
    direction. -- Albert Einstein
  • Uri Guttman at Aug 21, 2011 at 11:48 pm
    "JWK" == John W Krahn writes:
    JWK> There are a few ways to do what you require:

    and you missed the simplest one so far (i did mention edit_file):

    JWK> #!/usr/bin/perl
    JWK> use strict;
    JWK> use warnings;

    use File::Slurp qw( edit_file ) ;

    edit_file { s/Dood/Dude/g } $file ;

    and if you need a counter:

    my $change_cnt ;

    edit_file { $change_cnt = s/Dood/Dude/g } $file ;

    $change_cnt ||= 0 ;

    print "made my $change_cnt ;


    JWK> tie my @buffer, 'Tie::File', 'data.txt' or die "Cant open data.txt $!";

    JWK> for ( @buffer ) {
    JWK> s/Dood/Dude/ and last;
    JWK> }

    JWK> __END__


    JWK> #!/usr/bin/perl
    JWK> use strict;
    JWK> use warnings;

    JWK> local ( $^I, @ARGV ) = ( '', 'data.txt' );

    JWK> while ( <> ) {
    JWK> ?Dood? && s/Dood/Dude/;
    JWK> print;
    JWK> }

    JWK> __END__


    JWK> #!/usr/bin/perl
    JWK> use strict;
    JWK> use warnings;
    JWK> use Fcntl ':seek';

    JWK> open my $FP, '+<', 'data.txt' or die "Cant open data.txt $!";
    JWK> read $FP, my $buffer, -s $FP or die "Cant read from data.txt $!";
    JWK> seek $FP, 0, SEEK_SET or die "Cant seek on data.txt $!";
    JWK> $buffer =~ s/Dood/Dude/;
    JWK> print $FP $buffer;

    JWK> __END__



    JWK> John
    JWK> --
    JWK> Any intelligent fool can make things bigger and
    JWK> more complex... It takes a touch of genius -
    JWK> and a lot of courage to move in the opposite
    JWK> direction. -- Albert Einstein

    JWK> --
    JWK> To unsubscribe, e-mail: beginners-unsubscribe@perl.org
    JWK> For additional commands, e-mail: beginners-help@perl.org
    JWK> http://learn.perl.org/





    --
    Uri Guttman -- uri AT perlhunter DOT com --- http://www.perlhunter.com --
    ------------ Perl Developer Recruiting and Placement Services -------------
    ----- Perl Code Review, Architecture, Development, Training, Support -------
  • Uri Guttman at Aug 21, 2011 at 11:50 pm
    <sent before i finished>
    "JWK" == John W Krahn <jwkrahn@shaw.ca> writes:
    JWK> There are a few ways to do what you require:

    and you missed the simplest one so far (i did mention edit_file):

    JWK> #!/usr/bin/perl
    JWK> use strict;
    JWK> use warnings;

    use File::Slurp qw( edit_file ) ;

    my $file = 'data.txt' ;

    edit_file { s/Dood/Dude/g } $file ;

    and if you need a counter:

    my $change_cnt ;

    edit_file { $change_cnt = s/Dood/Dude/g || 0 } $file ;

    print "made $change_cnt changes to $file\n" ;

    uri

    --
    Uri Guttman -- uri AT perlhunter DOT com --- http://www.perlhunter.com --
    ------------ Perl Developer Recruiting and Placement Services -------------
    ----- Perl Code Review, Architecture, Development, Training, Support -------
  • Randal L. Schwartz at Aug 22, 2011 at 11:33 pm
    "John" == "John W Krahn" <jwkrahn@shaw.ca> writes:
    John> ?Dood? && s/Dood/Dude/;

    Deprecated in 5.14. Replace with m?Dood? and you're good though.

    --
    Randal L. Schwartz - Stonehenge Consulting Services, Inc. - +1 503 777 0095
    <merlyn@stonehenge.com> <URL:http://www.stonehenge.com/merlyn/>
    Smalltalk/Perl/Unix consulting, Technical writing, Comedy, etc. etc.
    See http://methodsandmessages.posterous.com/ for Smalltalk discussion
  • C.DeRykus at Aug 23, 2011 at 3:41 am

    On Aug 21, 4:33 am, xecro...@yahoo.com (Ron Weidner) wrote:
    Recently, I was asked to find the first occurrence of a word in a text file and replace it with an alternate word.  This was my solution.  As a new Perl programmer, I feel like this solution was too C like and not enough Perl like.  So, my question is what would have been the Perl like solution to this problem?

    In this example there is little risk of running out of memory reading the file.  But had this been a production environment or an unknown file size, I would have had to consider that.

    #!/usr/bin/perl
    use strict;
    use warnings;

    #program finds the first occurrence of the word Dood and
    #replaces it with the word Dude in the file data.txt.

    open FP, "+<", "data.txt" || die "Cant open data.txt " . $!;

    my @buffer = <FP>;
    seek FP,0,0;
    my $do_replace = 1; #used to control replacing in multiline files.
    my $line;
    my $data;
    foreach $data (@buffer)
    {
    if ($do_replace == 1)
    {
    $line = $data;
    $data =~ s/Dood/Dude/;
    if ($line ne $data)
    {
    $do_replace = 0; #we did a substitution so do no more.
    }
    }
    print FP $data;}

    close FP;

    #Test data
    #Dude! Where's my car?
    #Dood! Where's my car?
    #Dood! Where's my car?
    If you're permitted a one-liner:

    perl -pi.bak -e '$c=s/Dood\/Dude/ if !$c++' file

    --
    Charles DeRykus
  • John W. Krahn at Aug 23, 2011 at 5:00 am

    C.DeRykus wrote:
    If you're permitted a one-liner:

    perl -pi.bak -e '$c=s/Dood\/Dude/ if !$c++' file
    $ perl -c -pi.bak -e '$c=s/Dood\/Dude/ if !$c++'
    Substitution replacement not terminated at -e line 1.



    John
    --
    Any intelligent fool can make things bigger and
    more complex... It takes a touch of genius -
    and a lot of courage to move in the opposite
    direction. -- Albert Einstein

Related Discussions

Discussion Navigation
viewthread | post
Discussion Overview
groupbeginners @
categoriesperl
postedAug 21, '11 at 11:33a
activeAug 23, '11 at 5:00a
posts11
users7
websiteperl.org

People

Translate

site design / logo © 2022 Grokbase