简体   繁体   中英

Using sed to replace numbers

I'd like to replace some numbers in a file with the result of a calculation using the found number, and like to use sed on MacOSX. I've tried a lot of variants and now know I have to use -E to use modern instead of basic regular expression.

Some examples:

echo "bla 18934750 + wwv_flow_id.offset bla" | sed s/\ +\ wwv_flow_id.offset/blabla/

gives

bla 18934750blabla bla

So without the -E, it finds and replaces fixed text. But with the -E, it doesn't:

echo "bla 18934750 + wwv_flow_id.offset bla" | sed -E s/\ +\ wwv_flow_id.offset/blabla/

gives

bla 18934750 + wwv_flow_id.offset bla

In other words: no match and no change in the text. The ultimate goal is to find the number that precedes the fixed text " + wwv_flow_id.offset" and use that number and subtract a fixed number (say 750) from it, so the end result becomes:

bla 18934000 + wwv_flow_id.offset bla

And for that I need at least back references, which also don't work like I expected, because

echo "bla 18934750 + wwv_flow_id.offset bla" | sed -E s/\([0-9]+\)\ /\1/

gives

bla 1+ wwv_flow_id.offset bla

I hope some regex guru can help me out here.


UPDATE

With the help of ruakh, this is what I've got now:

echo "bla 18934750 + wwv_flow_id.offset bla" | sed -E 's/([0-9]+) \+ wwv_flow_id.offset/(\1-750) \+ wwv_flow_id.offset/'

which returns:

bla (18934750-750) + wwv_flow_id.offset bla

The bonus question now is, how to turn this into

bla 18934000 + wwv_flow_id.offset bla




UPDATE 2

I managed to achieve my desired result by combining sed with awk, like this:

echo "bla 18934750 + wwv_flow_id.offset bla" | sed -E 's/([0-9]+)([ ]*)\+([ ]*)wwv_flow_id.offset/~\1~\2\+\3wwv_flow_id.offset/' | awk -F~ '{print $1 $2-750 $3}'

(I know for sure there are no ~ tokens on the original line)

In "modern" regexes, + has a special meaning — it means "one or more" (just like how * means "zero or more") — so to match an actual plus sign, you need to use \\+ . Since you apparently prefer not to wrap your sed -script in quotes, you would write it as \\\\+ :

echo "bla 18934750 + wwv_flow_id.offset bla" | sed -E s/\ \\+\ wwv_flow_id.offset/blabla/

though I think it will make your life easier if you abandon that preference, and write:

echo "bla 18934750 + wwv_flow_id.offset bla" | sed -E 's/ \+ wwv_flow_id.offset/blabla/'

Quoting your argument will also address your back-reference issue, whereby Bash is translating \\1 to 1 :

echo "bla 18934750 + wwv_flow_id.offset bla" | sed -E 's/([0-9]+) /\1/'

though if you still prefer to stick with your non-quoted- sed -script style, you could write \\\\1 :

echo "bla 18934750 + wwv_flow_id.offset bla" | sed -E s/\([0-9]+\)\ /\\1/

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM