I am trying to move to perl (from sed). But how can I replace this sed expression with perl in a similarly short way?

sed -n '/patternmatch/s%stuff%changed%p' file

I need to search for a pattern, and only when the pattern is found, substitute "stuff" with "changed".

The only way I could do it was with an if statement which looks like this

perl -ne 'if ( /patternmatch/ ) { s%stuff%changed%; print }' file

Is it possible to do it as short as with sed? How?

PS: How to do it with python is here.

  • 3
    Just because it's Perl doesn't mean you have to make it shorter and less readable. Jul 15, 2015 at 23:35
  • @Gilles: Of course not. My next step will be to change from perl and shell-scripting in general to python, which is said to be more readable and less complicated.
    – erik
    Jul 15, 2015 at 23:40
  • 2
    sed, having single character command names, will probably win the golf match. Jul 16, 2015 at 13:29

2 Answers 2


Use the modifier form of if:

perl -ne 's/stuff/changed/, print if /patternmatch/'

or, you can use and and or for flow control:

perl -ne '/patternmatch/ and s/stuff/changed/, print'
  • The latter is an interesting example of the precedence difference between and and &&.
    – muru
    Jul 15, 2015 at 22:38
  • For the speed (with a text file of several hundred megabytes on a ramdrive): My sed command took real 9.919s, my if(){}-perl command took real 3.527s, your print-if-perl command took real 3.506s and your and-perl command took real 3.998s. This was reproducible. That means the print-if-variant is the fastest.
    – erik
    Jul 15, 2015 at 23:10
  • @erik Actually, it just means you don't understand what you're measuring. The relative speed of the two versions above depend on how many times /stuff/ matches, and how many times /patternmatch/ matches. Also, if you really need speed, you can still speed things up by adding an /o flag to both regexps.
    – lcd047
    Jul 16, 2015 at 6:26
  • @lcd047: IIRC, /o matters only if there's dynamic stuff in the pattern.
    – choroba
    Jul 16, 2015 at 8:57
  • 1
    flip-flop magic: perl -ne 'print if /patternmatch/..(s/stuff/changed/,1)' :) Jul 16, 2015 at 22:04


user@unix:~$ echo 'abc' | sed      's/abc/xyz/'

user@unix:~$ echo 'abc' | perl -pe 's/abc/xyz/'

user@unix:~$ echo 'abc' > file.txt && cat file.txt

user@unix:~$ sed      's/abc/xyz/' file.txt

user@unix:~$ perl -pe 's/abc/xyz/' file.txt


user@unix:~$ echo 'patternmatch' | sed      's/patternmatch/stuffchanged/'

user@unix:~$ echo 'patternmatch' | perl -pe 's/patternmatch/stuffchanged/'

user@unix:~$ echo 'patternmatch' > file.txt && cat file.txt

user@unix:~$ sed      's/patternmatch/stuffchanged/' file.txt

user@unix:~$ perl -pe 's/patternmatch/stuffchanged/' file.txt

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.