In GNU sed, I can display the result of successful substitution of the search pattern. Simple example as the following:

echo -e "nginx.service\nmariadb.service\nphp-fpm.service" > something.conf; sed -ri 's|(mariadb)(\.service)|postgresql-9.4\2|w sed-output.log' something.conf; [[ -s sed-output.log ]] && echo "Pattern found and modified. $(cat sed-output.log)" || echo "Pattern not found."; 

Because sed has limitation while dealing with multilines, I switched to perl.

echo -e "nginx.service\nmariadb.service\nphp-fpm.service" > something.conf; perl -i -pe 's|(mariadb)(\.service)|postgresql-9.4\2|' something.conf; 

The code above did the same like sed, but how can I get the modified content ("postgresql-9.4.service") into a file, or printed out?

Basically what I would like to achieve is, after the script has been executed, it tells me if it's successful (and what actually substituted) and if not, I'll display a message of what couldn't be found and replaced.


Edit:
Highlighted that I want to get (only-the-) modified content, which indicates that my script is successful. Because with perl -i -pe 's/pattern/replace/' file, I couldn't know if it return true or false. Of course I can simple do grep -E "/pettern/" to find out, but that's not the question.

3

3 Answers

This code will throw an exit code equal to 0 when replacement is done:

$ perl -i -pe '$M += s|(mariadb)(\.service)|postgresql-9.4\2|;END{exit 1 unless $M>0}' something.conf $ echo $? 0 

When NO substitution is done, return code will be 1:

$ perl -i -pe '$M += s|(maria)(\.service)|postgresql-9.4\2|;END{exit 1 unless $M>0}' something.conf $ echo $? 1 

From Perl documentation

An END code block is executed as late as possible, that is, after perl has finished running the program and just before the interpreter is being exited, even if it is exiting as a result of a die() function. (But not if it's morphing into another program via exec, or being blown out of the water by a signal--you have to trap that yourself (if you can).) You may have multiple END blocks within a file--they will execute in reverse order of definition; that is: last in, first out (LIFO). END blocks are not executed when you run perl with the -c switch, or if compilation fails.

Number of replacements returned from s operator

s/PATTERN/REPLACEMENT/msixpodualngcer

Searches a string for a pattern, and if found, replaces that pattern with the replacement text and returns the number of substitutions made.

1

It isn't as tidy in Perl because you have to open your log file explicitly, and for a one-liner that has to be in a BEGIN block. But Perl's s/// returns the number of changes made, so you can test it for truth

Note also that $2 is better than \2 in Perl, as the latter represents a character with code point 2, or Unicode U+0002 START OF TEXT

perl -i -pe ' BEGIN { open F, ">perl-output.log" } print F $_ if s|(mariadb)(\.service)|postgresql-9.4$2| ' something.conf 
1

You can check the output directly if you only print the substituted lines:

if [[ -z $(sed -n 's/mariadb\(\.service\)/postgresql-9.4\1/p' something.conf) ]]; then echo nope fi 

Your Answer

Sign up or log in

Sign up using Google Sign up using Facebook Sign up using Email and Password

Post as a guest

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.