admirabilis
admirabilis

Reputation: 2440

Manipulate ampersand in sed

Is it possible to manipulate the ampersand in sed? I want to add +1 to all numbers in a file. Something like this:

sed -i "s/[0-9]\{1,2\}/$(expr & + 1)/g" filename

EDIT: Today I created a loop using grep and sed that does the job needed. But the question remains open if anyone knows of a way of manipulating the ampersand, since this is not the first time I wanted to run commands on the replacement string, and couldn't.

Upvotes: 3

Views: 1219

Answers (3)

smci
smci

Reputation: 33970

sed will need to thunk out to some shell command (with '!') on each line to do that.

Here you think you are calling sed which then calls back to the shell to evaluate $(expr & + 1) for each line, but actually it isn't. $(expr & + 1) will just get statically evaluated (once) by the outer shell, and cause an error, since '&' is not at that point a number.

To actually do this, either:

  1. hardcode all ten cases of last digit 0..9, as per this example in sed documentation

  2. Use a sed-command which starts with '1,$!' to invoke the shell on each line, and perform the increment there, with expr, awk, perl or whatever.

  3. FOOTNOTE: I never knew about the /e modifier, which php-coder shows.

Upvotes: 1

Slava Semushin
Slava Semushin

Reputation: 15214

You may use e modifier to achieve this:

$ cat test.txt
1
2
$ sed 's/^[0-9]\{1,2\}$/expr & + 1/e' test.txt
2
3

In this case you should construct command in replacement part which will be executed and result will be used for replacement.

Upvotes: 2

Ray Toal
Ray Toal

Reputation: 88468

Great question. smci answered first and was spot on about shells.

In case you want to solve this problem in general, here is (for fun) a Ruby solution embedded in an example:

echo "hdf 4 fs 88\n5 22 sdf lsd 6" | ruby -e 'ARGF.each {|line| puts line.gsub(/(\d+)/) {|n| n.to_i+1}}'

The output should be

hdf 5 fs 89\n6 23 sdf lsd 7

Upvotes: 1

Related Questions