Beefy Boxes and Bandwidth Generously Provided by pair Networks
"be consistent"
 
PerlMonks  

perl one liner to replace matching string

by vinoth.ree (Monsignor)
on Jun 10, 2018 at 07:24 UTC ( #1216291=perlquestion: print w/replies, xml ) Need Help??

vinoth.ree has asked for the wisdom of the Perl Monks concerning the following question:

Hi

I am writing git pre-commit hook to verify the code before it get committed into git. As part of it I need to check the code extension correctly inserted in the code are not, if not I need to auto populate the file extension.

Below is the sample code begin get committed. Here the "@Filetyp" is empty, I need to update it with the file extension 'c'

@header_start
@Titel         : init 
@Filename      : test.c
@Filetyp       :
@Version       : 0001
@Produkt       : xx
@delivery      : xx
@date          : 20160610
@header_end

I tried the below perl one liner to replace the "@Filetyp :" as "@Filetyp :c"

my $ext='c'; qx("perl -p -i -e \"s/(\@Filetyp\\s*?:)/\\1$ext/\" /path/test.c")

Its get interpretered as below,

perl -p -i -e "s/(@Filetyp\s*?:)/\1c/" /path/test.c

But I did not get the expected output, it puts the 'c' letter in all the lines, as below

@header_start
@Titel         :c init 
@Filename      :c test.c
@Filetyp       :c
@Version       :c 0001
@Produkt       :c xx
@delivery      :c xx
@date          :c 20160610
@header_end

Pls someone tell me what I am doing wrong here...


All is well. I learn by answering your questions...

Replies are listed 'Best First'.
Re: perl one liner to replace matching string
by Athanasius (Bishop) on Jun 10, 2018 at 07:48 UTC

    Hello vinoth.ree,

    With warnings:

    use strict; use warnings; while (<DATA>) { s/(@Filetyp\s*?:)/\1c/; print; } __DATA__ @header_start @Titel : init @Filename : test.c @Filetyp : @Version : 0001 @Produkt : xx @delivery : xx @date : 20160610 @header_end

    Output:

    0:54 >perl 1895_SoPW.pl Possible unintended interpolation of @Filetyp in string at 1895_SoPW.p +l line 18. \1 better written as $1 at 1895_SoPW.pl line 18. Global symbol "@Filetyp" requires explicit package name (did you forge +t to declare "my @Filetyp"?) at 1895_SoPW.pl line 18. Execution of 1895_SoPW.pl aborted due to compilation errors. 17:41 >

    Perl sees @Filetyp as an (empty) array. Escape the sigil (and change \1 to $1):

    s/(\@Filetyp\s*?:)/$1 c/;.

    Output:

    17:44 >perl 1895_SoPW.pl @header_start @Titel : init @Filename : test.c @Filetyp : c @Version : 0001 @Produkt : xx @delivery : xx @date : 20160610 @header_end 17:44 >

    Hope that helps,

    Athanasius <°(((><contra mundum Iustus alius egestas vitae, eros Piratica,

      I tried the below perl one liner to replace the "@Filetyp :" as "@Filetyp :c"

      my $ext='c'; qx("perl -p -i -e \"s/(\@Filetyp\\s*?:)/\\1$ext/\" /path/test.c");

      I am already doing it.Could you pls try like above perl one liner to replace the string?


      All is well. I learn by answering your questions...

        Ok, I get the same result as you reported. Playing around with it, I had to add two additional backslashes to get it to work as desired (not sure why):

        my $ext='c'; qx("perl -p -i.bak -e \"s/(\\\@Filetyp\\s*?:)/\\1$ext/\" ./path/test.c +"); # ^^

        (Note: I also had to specify an extension for the backup file.) This is on Windows; if your O/S is different, it may treat the backslashes differently.

        Hope that helps,

        Athanasius <°(((><contra mundum Iustus alius egestas vitae, eros Piratica,

Re: perl one liner to replace matching string (updated)
by haukex (Bishop) on Jun 10, 2018 at 10:18 UTC
    qx("perl -p -i -e \"s/(\@Filetyp\\s*?:)/\\1$ext/\" /path/test.c")

    It is extremely rare that you need to call another perl from inside a Perl script! I'm going to guess that you're doing it for the effect of the -i flag? You can get that feature from inside Perl using $^I:

    { # new scope for local local @ARGV = '/path/test.c'; local $^I = ""; # -i command line switch while (<>) { s/(\@Filetyp\s*?:)/$1 c/; print; } }

    Update: qx// is often problematic anyway!

Re: perl one liner to replace matching string
by jwkrahn (Monsignor) on Jun 10, 2018 at 11:23 UTC
    qx("perl -p -i -e \"s/(\@Filetyp\\s*?:)/\\1$ext/\" /path/test.c")

    qx() is interpolated the same as a double quoted string so after interpolation the string "perl -p -i -e "s/(@Filetyp\s*?:)/\1$ext/" /path/test.c" is passed to the shell to execute.

    You should probably use single quotes around the substitution so that the shell doesn't mess with it, unless you are on Windows.

    The \1 capture variable should be $1 in the replacement string. \1 is only allowed inside the regular expression.

    To sum up, your code would be better written as (untested):

    my $ext = 'c'; qx(perl -p -i -e 's/\\Q@Filetyp\\E\\s*?:\\K/$ext/' /path/test.c)

    Although you may be better off using the solution that haukex provied.

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://1216291]
Approved by Athanasius
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others taking refuge in the Monastery: (5)
As of 2020-09-22 14:25 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?
    If at first I donít succeed, I Ö










    Results (129 votes). Check out past polls.

    Notices?