2

How can I apply this sed command to a specific line in a text file instead of to the entire file?

I found a solution here for replacing any IP addresses in a file with a specific address. I need to apply this command to a specific line in the file so that it only replaces one single unknown IP address. I saw that sed uses -n to filter but I literally know nothing about how to apply this to achieve my goal.

This code works for every IP in the file:

sed -e 's/[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}/x.x.x.x/g' test.txt

How can I apply it to the only line in the file that also includes the string, "ipv4" so that other lines containing IP addresses are left unmodified?

jww
  • 97,681
  • 90
  • 411
  • 885
  • The `-n` flag will suppress the output. Usually it's used with the 'p' command to print specific lines. – Steve Jun 10 '19 at 02:51
  • To state the obvious, that only works for IPv4 addresses. It breaks for IPv6 addresses. – jww Jun 10 '19 at 04:29
  • [edit] your question to include a [mcve] with concise, testable sample input and expected output to get the best help. – Ed Morton Jun 10 '19 at 14:59

3 Answers3

1

With , you can use a regex as an address like this:

sed -re '/ipv4/s/[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}/x.x.x.x/g' test.txt

If you don't specify -r, you'll need to escape the braces, i.e.:

sed -e '/ipv4/s/[0-9]\{1,3\}.[0-9]\{1,3\}.[0-9]\{1,3\}.[0-9]\{1,3\}/x.x.x.x/g' test.txt
Steve
  • 51,466
  • 13
  • 89
  • 103
  • Thank you for that. So adding /ipv4/ at the beginning of the command will only replace the IP on the one line that also includes the string ipv4? The full line is: "bind-address-ipv4": "x.x.x.x", – Doc Caliban Jun 10 '19 at 03:41
  • @DocCaliban exactly! Just adapt this pattern to fulfil your need – Allan Jun 10 '19 at 04:05
  • @DocCaliban: Does that work for you? Do you use `-e` or `-E` or `-r`? – Cyrus Jun 10 '19 at 04:29
  • That's not working for me. I am using -e If I leave out the /ipv4/ the overall command works by changing all IP addresses in the file. Still trying to target just the one line. – Doc Caliban Jun 10 '19 at 04:44
  • @DocCaliban: Sorry missed that one. You'll need to specify the `-r` flag to use extended regular expressions. Alternatively, you'll need to escape the braces. – Steve Jun 10 '19 at 05:10
0

You can skip over uninteresting lines:

sed '/ipv4/!b;s/YOUR PATTERN HERE/YOUR IP HERE/' input
perreal
  • 94,503
  • 21
  • 155
  • 181
0

If I get it right you want to find the first occurrence of the ip address on a line that also contains ipv4, and skip all other occurrences.

With GNU , try

sed -i -E '/ipv4/{s/[0-9]{1,3}(\.[0-9]{1,3}){3}/x.x.x.x/g;T;:a;n;ba}' test.txt

The -E will enable POSIX ERE syntax, no need to escape {} and (). The -i will replace inline in the file directly. /ipv4/ will find a line with ipv4 on it, and then {s/[0-9]{1,3}(\.[0-9]{1,3}){3}/x.x.x.x/g;T;:a;n;ba} will do the replacement only on that line. See potong's explanation of the T;:a;n;ba here

If you have a POSIX sed, try

sed -e '/ipv4/ {' -e 's/[0-9]\{1,3\}\(\.[0-9]\{1,3\}\)\{3\}/x.x.x.x/g' -e ':a' -e n -e 'ba' -e '}' file > newfile
Ryszard Czech
  • 18,032
  • 4
  • 24
  • 37
  • Thanks! When I try that I get an unterminated { error, but I don't see a problem in the code. – Doc Caliban Jun 11 '19 at 03:09
  • 1
    @DocCaliban Interesting, I just [tested](https://ideone.com/RZzuzF) this code and it looks working, i.e. it replaces the first occurrence of the IP on a line having `ipv4` substring. Do you have a GNU sed? Are you using variables? – Wiktor Stribiżew Jun 12 '19 at 22:01
  • @DocCaliban As it has been pointed out by Wiktor, the code is not causing errors, kindly please check your code. Share the exact code you are using if possible. – Ryszard Czech Jun 14 '19 at 15:41
  • Hello. I must be using a version of sed that is not cooperating. It's whatever comes with my QNAP NAS. – Doc Caliban Jun 14 '19 at 18:54
  • @DocCaliban Sorry, no idea what version of `sed` is used there. Try these two: 1) `sed '/ipv4/{s/[0-9]\{1,3\}\(\.[0-9]\{1,3\}\)\{3\}/x.x.x.x/g;T;:a;n;ba}' file` or 2) `sed -e '/ipv4/ {' -e 's/[0-9]\{1,3\}\(\.[0-9]\{1,3\}\)\{3\}/x.x.x.x/g' -e T -e ':a' -e n -e 'ba' -e '}' file`. If neither works, try `sed -e '/ipv4/ {' -e 's/[0-9]\{1,3\}\(\.[0-9]\{1,3\}\)\{3\}/x.x.x.x/g' -e ':a' -e n -e 'ba' -e '}' file` which is a bit less precise, but seems to work in POSIX mode. – Ryszard Czech Jun 26 '19 at 16:24