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.

3 Years
Discussion Span
Last Post by nicetapo

You can simlpily do like so:

use warnings;
use strict;

my $str = 'cat/dog/cat';

print $str;  #cat/tiger/deer


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.

Edited by 2teez


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 
$ perl -p -i -e 's#cat/dog/cat#cat/tiger/deer#' file.txt 
$ cat file.txt 



Edited by doubi: Incomplete.

This article has been dead for over six months. Start a new discussion instead.
Have something to contribute to this discussion? Please be thoughtful, detailed and courteous, and be sure to adhere to our posting rules.