matching multiple line string with perl regex and doing a replace

前端 未结 4 2071
孤城傲影
孤城傲影 2021-01-24 00:06

I have a source file where I use a macro to do logging. Typical logging lines look like:

STDOUT_LOG(logDEBUG4) << \"a single line log text\" << aVari         


        
4条回答
  •  悲哀的现实
    2021-01-24 00:28

    With $log string containing the whole log, with newlines and all,

    $log =~ s/STDOUT_LOG\K \( ( [^)]+ ) \) ( [^;]+ );/($1,$2);/xs;
    

    The [^)]+ matches up to the first closing parentheses, and likewise [^;]+ goes to the first ;. You do not need nor want the /g modifier. The /x allows spaces for readability.

    The \K is a particular form of the positive lookbehind, which also discards all previous matches. So the pattern before it, used as an assertion, is not affected by the substitution. See it in perlretut. It is not essential here, but if you leave it out then STDOUT_LOG is consumed by the match and so it need be typed in as well in the replacement part. It's just cleaner this way.

    Since there could be a problem with how the log is input here is a complete program

    use warnings 'all';
    use strict;
    
    my $logfile = 'log.txt';
    my $log = do {
        local $/; 
        open my $fh, '<', $logfile or die "Can't open $logfile: $!";
        <$fh>;
    };
    # print $log;
    
    $log =~ s/STDOUT_LOG\K \( ([^)]+) \) ([^;]+);/($1,$2);/xs;
    
    print $log;
    

    The do block allows us to slurp the whole file $logfile into the $log variable, by unsetting $INPUT_RECORD_SEPARATOR (or $/), within the block by local. See discussions in perlvar.


    If this is meant to be done with a one-liner

    perl -0777 -pe 's/STDOUT_LOG\K \( ([^)]+) \) ([^;]+);/($1,$2);/xs;' log.txt
    

    The -0777 makes it slurp the whole file into $_, and the substitution is by default done on it. The -p also prints $_ after each line is processed (and here we only have one "line" -- the whole file). See perlrun for command line switches and General Variables in perlvar for $_.


    Both these assume that the shown example of a log (one-liner or the multi-line one) stands on its own, that there is a single log-string to process. For simplicity I took that to be in a file log.txt and read it from that file, into the $log variable in the script and into $_ in the one-liner.

提交回复
热议问题