You didn't specify exactly what your requirements are. You may want a multi-step process. Pick a string that you know will not occur in your input (e.g., ####
):
echo "The quick brown fox jumps over 42 lazy dogs in 2012 and 2013." \
| sed \
-e "s/[0-9]\{4\}/&####/" \
-e "s/fox.*####//" \
-e "s/####//"
(Command excessively folded for readability.) The -e "s/[0-9]\{4\}/&####/"
injects ####
after the first four-digit number. (Warning: this will change 65536
to 6553####6
.)
-e "s/fox.*####//"
affects lines that contain fox
and ####
-- i.e., lines which contain at least one four-digit number -- and then deletes from fox
through the first four-digit number.
-e "s/####//"
, of course, cleans out any ####
strings that are left over from lines that contain a four-digit number but not fox
.
To also remove one space after the number if there is one,
echo "The quick brown fox jumps over 42 lazy dogs in 2012 and 2013." \
| sed \
-e "s/[0-9]\{4\}/&####/" \
-e "s/fox.*#### //" \
-e "s/fox.*####//" \
-e "s/####//"
Warning: You can add g
to all the s
commands, but, since this still uses .*
, which is the root of your problem, it will still not handle
One fox jumps in 2012 and 2013, another fox will jump in 2014 and 2015.
the way you probably want. And, of course, you don't want to add g
to "s/[0-9]\{4\}/&####/"
because then it will inject ####
after every four-digit number, defeating the whole point. Then the "s/fox.*####//"
will end up acting just like "s/fox.*[0-9]\{4\}//"
(your original command with the non-contributing characters removed); i.e., it will change
The quick brown fox jumps in 2012 and 2013.
to
The quick brown fox jumps in 2012#### and 2013####.
and then to
The quick brown .
The standart quantifiers in regular expressions are greedy, meaning they match as much as they can. – kinokijuf – 2012-09-18T10:33:14.093