I would like to replace 'cat/dog/cat' with 'cat/tiger/deer' in a particular .txt file. How should I do this in perl?

I tried /usr/bin/perl -p -i -e "s/'cat/dog/cat'/'cat/tiger/deer'/g" sample.txt
but it didn't work.

Recommended Answers

All 3 Replies

Hi,
You can simlpily do like so:

use warnings;
use strict;

my $str = 'cat/dog/cat';
$str=~s{dog/cat$}{tiger/deer};

print $str;  #cat/tiger/deer
OR

You can run the following from Command Line Interface:
perl -we '$_=q[cat/dog/cat];s{cat/dog/cat$}{print qq[cat/tiger/deer\n]}e;'

You don't need the modifier g. If you are reading the string from a file you might have to use open function in perl.

This can easily be achieved on a oneliner code too.

The basic answer to your question, nicetapo, is that you don't have to use / as the delimeter for the substitution operator, as 2teez indicated. Quote from perlretut:

And finally, the "//" default delimiters for a match can be changed to arbitrary delimiters by putting an 'm' out front:

    "Hello World" =~ m!World!;   # matches, delimited by '!'
    "Hello World" =~ m{World};   # matches, note the matching '{}'
    "/usr/bin/perl" =~ m"/perl"; # matches after '/usr/bin',
                                 # '/' becomes an ordinary char

"/World/", "m!World!", and "m{World}" all represent the same thing.  When, e.g., the quote (""") is used as a delimiter, the
forward slash '/' becomes an ordinary character and can be used in this regexp without trouble.

It's kind of awkward when it says "e.g., the quote"; it really means, "when anything but the forward slash is used as the delimeter, the forward slash itself becomes an ordinary character and can be used in the regexp without trouble.

It's also worth pointing out that, as 2teez showed, if you decide to use braces or other 'paired' characters as delimeters for any matching operators which do substitution (like s/// or tr///), the delimeters of the match part and the substitution part have to correspond.

Personally I avoid paired delimeters a) because I feel the back-to-back braces (or whatever) look unnatural, b) because it makes more sense to me to replace one single character (/) with another single character if you can, and c) because you end up with a couple of characters more to type.

However, you could argue that using braces as the delimeters is more clear (especially to someone who isn't familiar with the full syntax; s{cat/dog/cat}{cat/tiger/deer} would probably be more obvious than s#cat/dog/cat#cat/tiger/deer#. The latter looks a lot more like Perl living up to its unkind and over-stated 'line noise' reputation :)

So, the solution to your problem is very simple (here I use # instead of /):

$ echo 'cat/dog/cat' > file.txt
$ cat file.txt 
cat/dog/cat
$ perl -p -i -e 's#cat/dog/cat#cat/tiger/deer#' file.txt 
$ cat file.txt 
cat/tiger/deer

HTH,

--doubi

That was very helpful! Thanks, doubi and 2teez.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.