2

I have some text with ip inside it. I'd like to replace each digit in ip which is not followed by "SpecialWord" with some other character. There is can be more than one ip in each line.
For example:
This input
*random text with different numbers* 255.43.23.8 *some more text* "SpecialWord" 32.123.21.44 *text again*
Must become
*random text with different numbers* aaa.aa.aa.a *some more text* "SpecialWord" 32.123.21.44 *text again*
I tried to use
sed -r 's/([0-9]{1,3}\.){3}[0-9]{1,3}/.../g'
but I don't know exact number of digits in ip and sed can't do lookahead stuff. What can help me here?

  • Is there always a space on each side of the IP addresses in your search? – MikeD Mar 20 '17 at 2:30
  • Is that supposed to be a single line? Do you want to replace all IP addresses preceding "SpecialWord", or only the first, or only the last? – Michael Vehrs Mar 20 '17 at 10:15
  • 1
    In your example, 32.123.21.44 is not followed by "SpecialWord", and therefore should be changed, but you left it untouched. On the other hand, 255.43.23.8 is followed by "SpecialWord", albeit not directly, and you changed it. Should "follow" be understood as "directly follow"? – xhienne Mar 20 '17 at 10:59
  • This issue can not be solved reliably if the text surrounding the IP address is random, i.e. if it's allowed to contain IP addresses. – Kusalananda Sep 24 '17 at 19:04
0

I am not sure regexp can remember length of pattern, so for a pure (partial) sed solution :

edit:

this was a little trickier.

I came up with a sed file a.sed

p
s/[0-9]\.[0-9]/a.a/g
s/with/phase 1/
p
s/[0-9]a\.a/aa.a/g
s/a\.a[0-9]/a.aa/g
s/phase 1/phase 2/
p
s/[0-9]aa.a/aaa.a/g
s/a.aa[0-9]/a.aaa/g
s/phase 2/final/

this basically do the same as command line, but with debug line.

  • first line ( - first line turn 1.2 into a.a (please note that digit in text, such as 1.12% will be turn into a.a2%)
  • next lines build up for two and three digit IP.) turn 1.2 into a.a (please note that digit in text, such as 1.12% will be turn into a.a2%)
  • next lines build up for two and three digit IP.
  • remove line with p and s/phase x/../ when OK

use

sed -f a.sed u 

where u is (yes that's not valid IP, but that's not the point either)

*random text with different numbers* 255.43.23.8 *some more text* "SpecialWord" 32.123.21.44 *text again*
*random text with different 12* 255.4.2.8 *some more text* "SpecialWord" 32.12.21.44 *text again*
*random text with different 13* 255.453.263.788 *some more text* "SpecialWord" 2.123.21.454 *text again*
*random text with different 1.12%* 255.43.23.8 *some more text* "SpecialWord" 32.123.21.44 *text again*
*random text with different numbers* 5.43.23.8 *some more text* "SpecialWord" 32.3.1.44 *text again*

this wil result in

*random text final different numbers* aaa.aa.aa.a *some more text* "SpecialWord" aa.aaa.aa.aa *text again*
*random text final different 12* aaa.a.a.a *some more text* "SpecialWord" aa.aa.aa.aa *text again*
*random text final different 13* aaa.aaa.aaa.aaa *some more text* "SpecialWord" a.aaa.aa.aaa *text again*
*random text final different a.aa%* aaa.aa.aa.a *some more text* "SpecialWord" aa.aaa.aa.aa *text again*
*random text final different numbers* a.aa.aa.a *some more text* "SpecialWord" aa.a.a.aa *text again*

edit2 : if you can afford temporary file

grep -Eo '[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}' u > v

get a list of IP in v

sed s/[0-9]/a/g v > w

turn to anonnymous IP in w

paste -d '/' v w | sed -e 's|^.*$|s/&/|'

generate a sed file that turn IP to anonnymous IP ...

paste -d '/' v w | sed -e 's|^.*$|s/&/|' | sed -f - u

... and apply to file.

result is same as above, except for line with 1.12%

*random text with different 1.12%* aaa.aa.aa.a *some more text* "SpecialWord" aa.aaa.aa.aa *text again*

this suppose you can have temporary files, and like to use cruise missile to kill rabbit.

0

Replacing IPs unconditionally can be done with:

perl -pe 's!(\d+(\.\d+){3})! $1 =~s/\d/a/gr !ge' 

Explanation: substitute IPs with the result of (substitute digits by "a")

In order to protect IPs after "SpecialWord", mark IPs with a "#" (and remove it in the end)

perl -pe 's/"SpecialWord"\s*\d+/$&#/; 
          ..... 
          s/#//'

All together:

perl -pe 's/"SpecialWord"\s*\d+/$&#/; 
          s!(\d+(\.\d+){3})! $1 =~s/\d/a/gr !ge;
          s/#//'   file

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.