2

How do I replace a string between two delimiters?

Some of the answers I found are close, but I think my need is a little more complex.

I.e. smb.conf contains a blank line between shares. I want to target the share I want to update. The first delimiter is "[sharename]" and the end delimiter can be a blank line.

I want to find and replace "writable = yes" with "writable = no" which may be inexactly formatted because of white space, but must occur between my two delimiters.

Gerald Schneider
  • 23,274
  • 8
  • 57
  • 89

4 Answers4

1

Almost there, thanks to this list and http://fahdshariff.blogspot.com/2012/12/sed-mutli-line-replacement-between-two.html.

I am able on the command line to replace the "writeable" with "# writeable" and can do so without regard to the Y/N setting, I insert another line later on.

sed '/\[${share_name}\]/,/^$/{/\[${share_name}\]/n;/^$/!{s/writeable/\#writeable/g}}' \
< ${input_file} \
> /tmp/parse-smb.tmp

While this works on the command line with the "!" escaped "!" it doesn't work in a script file, /bin/sh. I have to remove the escape but then the trigger doesn't hit.

Shell subtleties.

U880D
  • 1,017
  • 2
  • 12
  • 18
1

Ah, the "!" was fine, it was the failure of the "share_name" variable to translate. Use double rather than single quotes in this command.

sed "/\${share_name}\]/,/^$/{/[${share_name}\]/n;/^$/!s/writeable/\#writeable/g}}" \
< ${input_file} \
> /tmp/parse-smb.tmp

Should have realized that the subsequent line also used double quotes.

sed -i "s/\[${share_name}\]/\[${share_name}\]\n\thosts allow = 10.50.157.0\/24 \n\twriteable = no/" \
/tmp/parse-smb.tmp
U880D
  • 1,017
  • 2
  • 12
  • 18
0

I'd consider perl: untested

perl -00 -pe '/^\[your_share_name\]/ and s/writable\s*=\s*\Kyes/no/si' smb.conf
glenn jackman
  • 4,630
  • 1
  • 17
  • 20
0

I think this is a job for perl (or python if you're so inclined.)

iMac$ cat ./replace.pl
#!/usr/bin/perl

while (<>) {
    if (/^\n/) { $replace = 0; }
    if (/\[share3\]/) { $replace = 1; }
    print unless /writable/;
    if (/writable/) {
    if ($replace == 1) {
        print "  writable = no\n";
    }
    else {
        print;
    }
    }
}
iMac$ cat smb.conf 
[share1]
  writable = yes
  user = anonymous
  host = remote

[share2]
  writable = yes
  user = anonymous
  host = remote

[share3]
  writable = yes
  user = anonymous
  host = remote

[share4]
  writable = yes
  user = anonymous
  host = remote

[share5]
  writable = yes
  user = anonymous
  host = remote
iMac$ cat smb.conf | ./replace.pl
[share1]
  writable = yes
  user = anonymous
  host = remote

[share2]
  writable = yes
  user = anonymous
  host = remote

[share3]
  writable = no
  user = anonymous
  host = remote

[share4]
  writable = yes
  user = anonymous
  host = remote

[share5]
  writable = yes
  user = anonymous
  host = remote
toppledwagon
  • 4,245
  • 25
  • 15