1

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. – Gilles Jul 15 '15 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 '15 at 23:40
  • 2
    sed, having single character command names, will probably win the golf match. – glenn jackman Jul 16 '15 at 13:29
9

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 '15 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 '15 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 '15 at 6:26
  • @lcd047: IIRC, /o matters only if there's dynamic stuff in the pattern. – choroba Jul 16 '15 at 8:57
  • 1
    flip-flop magic: perl -ne 'print if /patternmatch/..(s/stuff/changed/,1)' :) – Evgeny Vereshchagin Jul 16 '15 at 22:04
0

's/abc/xyz/'

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

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

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

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

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

's/patternmatch/stuffchanged/'

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

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

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

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

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

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.