substitution using perl

Hi All,

I need the perl version of the below sed command:

sed 's/abc.*/&.txt/g' <filename>

Because I'm trying to do some replacement recursively using perl and the above replacement is replacing the abc* with "&.txt" exactly.

Thanks,
Arun

$
$ # The data file
$ cat -n f3
     1  abcdefghij
     2  the quick brown fox abc
     3  yet another line
     4  abcdef abcdef abcdef
     5  the abc quick brown abcd fox abcde
$
$ # conversion with sed
$ sed 's/abc.*/&.txt/g' f3
abcdefghij.txt
the quick brown fox abc.txt
yet another line
abcdef abcdef abcdef.txt
the abc quick brown abcd fox abcde.txt
$
$ # conversion with Perl
$ perl -pne 's/(abc.*)/$1.txt/g' f3
abcdefghij.txt
the quick brown fox abc.txt
yet another line
abcdef abcdef abcdef.txt
the abc quick brown abcd fox abcde.txt
$
$

tyler_durden

1 Like

should be

perl -pe 's/(abc.*)/\1.txt/'

iirc

1 Like

Looks like you want to append .txt to any line which contains abc?

perl -nle 'if ($_ =~ m/abc /) { $_ =~ s/$/\.txt/; print $_}' file

Tytalus,

Thanks that works fine. But how to check the exact match of abc

For example if a file has

abc
abcd

the command should replace only the line that contains abc and not the abcd with .txt at the end

Thanks all for the kind reply..

$
$ cat f3
abc
abcd
$
$ perl -pne 's/(abc)$/$1.txt/' f3
abc.txt
abcd
$
$

tyler_durden

Tyler,

Sorry I made a mistake, I need it like

Input:

 1  abcdefghij
 2  the quick brown fox abc
 3  yet another line
 4  abcdef abcdef abcdef
 5  the abc quick brown abcd fox abcde

Output

 1  abcdefghij
 2  the quick brown fox abc.txt
 3  yet another line
 4  abcdef abcdef abcdef
 5  the abc quick brown abcd fox abcde.txt

Thanks again...

What's the difference between rows (2) and (5) ?

  • Row (2) ends with "abc", so you want ".txt" at its end.
  • But Row (5) does not end with "abc". So why a ".txt" at its end ?
  • Row (5) is similar to Row (4) because neither of them ends with "abc", so why not a ".txt" at the end of Row (4) ?

tyler_durden

Sorry, my bad. I guess you are checking for existence of the word abc anywhere in the line.

$
$ cat f3
abcdefghij
the quick brown fox abc
yet another line
abcdef abcdef abcdef
the abc quick brown abcd fox abcde
$
$
$ perl -lne 'print /\babc\b/ ? "$_.txt" : $_' f3
abcdefghij
the quick brown fox abc.txt
yet another line
abcdef abcdef abcdef
the abc quick brown abcd fox abcde.txt
$
$

tyler_durden

Tyler,

This is what I expected and thanks a lot for your effort. If possible could you please explain the command.

Arun

perl -lne 'print /\babc\b/ ? "$_.txt" : $_' f3

A couple of things that you should know first:

(a)
$_ represents the current line of file f3 that is being processed by the Perl one-liner.

(b)
In regular expression terminology, "\b" is a word boundary. It doesn't represent a character in a string, but a condition at a certain position. It's a zero-width assertion.

(c)
The regular expression "\babc\b" means - a word boundary, followed by literal characters "a", "b", "c", followed by another word boundary. In effect, it matches the word "abc".

(d)
// is Perl's pattern match operator. So, /\babc\b/ means the word "abc" is searched. Searched where ? Searched in the current line $_. If it is not mentioned, Perl assumes that the current line is to be searched.

All the following forms are equivalent:

/\babc\b/
$_ =~ /\babc\b/
$_ =~ m/\babc\b/

which can be seen here:

$
$ perl -lne 'print /\babc\b/ ? "$_.txt" : $_' f3
abcdefghij
the quick brown fox abc.txt
yet another line
abcdef abcdef abcdef
the abc quick brown abcd fox abcde.txt
$
$ perl -lne 'print $_ =~ /\babc\b/ ? "$_.txt" : $_' f3
abcdefghij
the quick brown fox abc.txt
yet another line
abcdef abcdef abcdef
the abc quick brown abcd fox abcde.txt
$
$ perl -lne 'print $_ =~ m/\babc\b/ ? "$_.txt" : $_' f3
abcdefghij
the quick brown fox abc.txt
yet another line
abcdef abcdef abcdef
the abc quick brown abcd fox abcde.txt
$

(e)
"?:" is the ternary operator that Perl borrowed from C. It works like an "if-then-else" - if the argument before the ? is true, the argument before the : is returned, otherwise the argument after the : is returned.

So in this one-liner, if /\babc\b/ is true, then "$_.txt" is returned i.e. the current line followed by ".txt" is returned.

If /\babc\b/ is false, then $_ is returned i.e. the current line is returned as it is.

(f)
The "print" function prints the value returned at (e) to the standard output.

So, essentially the Perl one-liner searches for the word "abc" in the current line of file f3. If found, it prints current line followed by ".txt". Otherwise, it simply prints the current line.

It does this for all lines of file f3 due to the "n" command-line option (the "n" in -lne).

The one-liner could be written in a verbose manner thusly -

$
$ perl -lne 'if ($_ =~ m/\babc\b/) { print "$_.txt" } else { print $_ }' f3
abcdefghij
the quick brown fox abc.txt
yet another line
abcdef abcdef abcdef
the abc quick brown abcd fox abcde.txt
$
$

In fact, you could be more verbose and write a Perl program that uses the "open" and "close" functions and while loop to open, process and close the file.

HTH,
tyler_durden

1 Like