Reputation: 33
I want to change a line in a bunch of similar scripts using sed. Some of these scripts do not actually contain the line I want to change. However, sed doesn't tell me it didn't change the line cause it wasn't there. Any ideas on how I can make sed spit out a warning? Say, I have script one
log export ALBET=0.155
log export ALBEG=0.218
log export RADGHGCOEF=1.0
and script two
log export ALBET=0.168
log export ALBEG=0.201
then
sed -i 's/RADGHGCOEF=.*/RADGHGCOEF=2.0/' script
works on both on them, but I'd like to be informed that there was actually no line containing RADGHGCOEF to be changed in script 2. Thanks!
Upvotes: 3
Views: 792
Reputation: 19982
Testing with grep
before the sed
(like @Sundeep suggested in a comment) is better than manipulating weird options of sed
. This solution is just for fun:
You can let sed
write something to stderr when it finds a string:
sed 's/RADGHGCOEF=.*/RADGHGCOEF=2.0/; /RADGHGCOEF/e echo yes >&2' script
I like to have it on stderr, avoiding it being written into the file when you add -i
.
When you want to test
the output, you want to convert stderr back to stdout.
Putting things together:
test -z "$(sed -i 's/RADGHGCOEF=.*/RADGHGCOEF=2.0/;
/RADGHGCOEF/e echo yes >&2' script 2>&1)" && echo "Nothing found"
Upvotes: 1
Reputation: 6798
Code snippet to make desired replacement, default output to screen (final message printed to STDERR
).
Run script with option -i
for in-place replacement - perl -i script.pl file_name
use strict;
use warnings;
use feature 'say';
my $count;
while( <> ) {
chomp;
$count ++ if s/RADGHGCOEF=.*/RADGHGCOEF=2.0/;
say;
}
if( $count ) {
say STDERR "Info: replaced $count time(s)";
} else {
say STDERR "Info: nothing to replace";
}
Input file some_data
log export ALBET=0.155
log export ALBEG=0.218
log export RADGHGCOEF=1.0
Run as ./script.pl some_data
log export ALBET=0.155
log export ALBEG=0.218
log export RADGHGCOEF=2.0
Info: replaced 1 time(s)
Run as perl -i script.pl some_data
Info: replaced 1 time(s)
Upvotes: 0
Reputation: 12337
Use this Perl one-liner:
perl -i -pe '$found++ if s/RADGHGCOEF=.*/RADGHGCOEF=2.0/; END { warn "$ARGV: not found\n" if !$found; }' script
The Perl one-liner uses these command line flags:
-e
: Tells Perl to look for code in-line, instead of in a file.
-p
: Loop over the input one line at a time, assigning it to $_
by default. Add print $_
after each loop iteration.
-i
: Edit input files in-place (overwrite the input file).
$ARGV
: current input file name.
$found++ if s/.../.../
: increment by 1 the $found
variable from its undef
initial value, so that it now becomes 1 (or more, depending on how many times the substitution occurred).
END { ... }
: execute the code after reading the entire input file.
if !$found
: if the substitution never occurred, $found
is false
in boolean context), otherwise true
.
SEE ALSO:
perldoc perlrun
: how to execute the Perl interpreter: command line switches
perldoc perlvar
: Perl predefined variables
Upvotes: 5
Reputation: 784868
You can use this awk
solution instead of sed
:
awk '{n += sub(/RADGHGCOEF=.*/, "RADGHGCOEF=2.0")} 1; END{exit !n}' file &&
echo 'search string found!' || echo 'search string not found!'
This command will exit with 1
is substitutions occurred otherwise it wil exit with 0
.
Upvotes: 4