3

I have a bunch of config files looking as follows:

reader_0 = newcamd({
name = "Oct 1",
host = "hostname 1",
port = 27020,
user = "UNAME",
pass = "password1",
key  = "0102030405060708091011121314",
})

reader_1 = newcamd({
name = "Oct 2",
host = "hostname 2",
port = 27020,
user = "UNAME",
pass = "password2",
key  = "0102030405060708091011121314",
})

How can replace a port number 27020 with another one, for example, 22443, in the section 'reader_1' using sed?

Thank you.

  • 2
    I think there's a formatting error in your post: You didn't put the four spaces before the closing braces }). This raises the question: Are the two sections from different files or do they belong to one file? – Stefan Hamcke Jan 10 at 15:14
  • 1
    Are you having reader_3 also? – Prvt_Yadv Jan 10 at 15:17
  • 1
    What's fixed and what's variable? Is "reader_1 = newcamd({" fixed? Is the existing port always 27020 or can that vary? – Jeff Schaller Jan 10 at 15:49
  • Will the reader_1 section always have a "port" definition? – Jeff Schaller Jan 10 at 15:57
  • @JeffSchaller Yes, all reader_* sections have a 'port' parameter. The existing port number is 27020 in all files. All variables are actually constant and same in all files. – Viktor Zaionchkovskyi Jan 11 at 7:15
2

If you have multiple similar lines in the same file you would have to type:

sed -i ':a;N;$!ba; s/27020/22443/2' file

Where /2 would mean that it will replace the second match for 27020. You can test the command with the command sed without the -i parameter in order to see which result gives you.

Otherwise with a simple sed -i 's/27020/22443/g' file it would be valid, as long as you know which file modify.

  • 1
    Thank you. This is what I've been looking for! – Viktor Zaionchkovskyi Jan 11 at 7:41
  • I used this command for multiple files sed -i -- ':a;N;$!ba; s/27020/22443/2' * – Viktor Zaionchkovskyi Jan 11 at 7:46
6

Using sed's predecessor ed:

ed -s input <<< $'/^reader_1 =\n/^port =\nc\nport = 22443,\n.\nw\nq'

This sends ed an ANSI-quoted here-string of commands to edit the file. The commands are, in sequence:

  1. /^reader_1 = -- search for the line beginning with "reader_1 ="
  2. /^port = -- search forwards from there for the line beginning with "port ="
  3. c -- change that line
  4. port = 22443, -- to that text
  5. . -- end the replacement text
  6. w -- write the file to disk
  7. q -- quit ed

You could tighten or loosen the regular expressions to match more or less carefully, according to your actual data.

3

I am assuming that reader_0 has host = hostanme 1, reader_1 has host = hostname 2 and so on.

You can use this command to replace from file:

sed -i '/host = "hostname 2",/{N;s/port = 27020,/port = 22443,/}' file
  • 2
    This also assumes that port always follows host. If we assume that the fields and their orders are always the same, then you can also add 2 additional Ns and match from /^reader_1\b/ instead of /host = "hostname 2",/. – JoL Jan 10 at 21:27
  • Yeah, that will be more general. – Prvt_Yadv Jan 11 at 5:44
1

This might be better done with awk in which you can use a state-machine style technique:

awk '/^reader_1 = newcamd\({/ { section_found = 1} /})/ { section_found = 0 } section_found && /port = 27020,$/ { sub(/27020,$/, "22443,") } { print }' file1 > file2 && mv file2 file1

Explanation:

Set a flag when the section start is found:

/^reader_1 = newcamd\({/ {
    section_found = 1
}

Clear the flag when the end of a section is found:

/})/ {
    section_found = 0
}

Substitute the new port number when in the right section and on the right line:

section_found && /port = 27020,$/ {
    sub(/27020,$/, "22443,")
}

Print all lines:

{
    print
}

Send output to file2 (a temporary file):

> file2

If everything was successful, rename file2 to file1:

&& mv file2 file1

You can make the regular expressions as loose or tight as you need.

This type of code is easier to read and maintain than sed or ed code, especially if you format it similarly to the way I have in my explanation.

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.