Even to Odd converter

Here is an interesting problem: write a sed script to substitute every even number with the nearest odd number. I got this one from the list of the latest searches which bring the users to this site.
Let’s see how we can tackle this issue.

First of all, let me say that, for this type of tasks, I’d rather use awk because it has variables and strong and fast arithmetics capabilites. Here is how I’d do in awk:

$ echo "12 15 4 98 1123" | awk '{
for (i=1;i<=NF;i++)
if ($i ~ /^[0-9]*[02468]$/)
$i--
} 1'

The above command ignores numbers mixed with strings (i.e. foo12, 4bar2,etc.) and simply subtracts 1 from any even number (though you can easily add 1 by using $i++ in the place of $i–).

On the other hand, with sed we neither have variables nor any addition/subtraction operator, therefore we have to use a totally different algorithm:

$ echo "10 foo 16 bar 0 cat 98 day 1123" | sed 's/\<\([0-9]*\)0\>/\11/g;
s/\<\([0-9]*\)2\>/\13/g;
s/\<\([0-9]*\)4\>/\15/g;
s/\<\([0-9]*\)6\>/\17/g;
s/\<\([0-9]*\)8\>/\19/g;'

The above script1 considers five different cases: the number ends with a 0, with a 2, with a 4, with a 6 or with a 8. In every case, it substitutes the least significant digit with the odd number just above. For example,

s/\<\([0-9]*\)2\>/\13/g;

convert every number ending with 2 to the same number but with 3 as the last digit.

By the way, I craftily added one unit to all the even numbers because I didn’t want to solve the problem of decrementing a number ending with a 0: 10 -> 9, 100 -> 99, 1000 -> 999 etc.
It shouldn’t be too much harder but I bet it’d be a bit longer
()

Reference:

  1. Because of the word boundaries characters (\< and \>) it’ll only work with gnu sed and other non official implementations of sed. You can avoid word boundaries if you don’t need to prevent patterns like “foo123″ from being converted by the script. For more info: http://www.linuxtopia.org/online_books/linux_tool_guides/the_sed_faq/sedfaq6_009.html

None
A comma-separated list of terms describing this content. Example: funny, bungee jumping, "Company, Inc.".