regexp and sed find block of string in multiline block untill it end with space

Viewed 130

I try to capture those blocks of strings and comment on them using regexp and sed. each block separated with space

some text here 
some text here 

AppServer1:
  name: ${AppServer1.name}
  ip: ${AppServer1.ip}
   
some text here 
some text here 

AppServer2:
  name: ${AppServer1.name}
  ip: ${AppServer1.ip}

some text here 
some text here 
   

I try with this regexp:

sed E '/./{H;1h;$!d} ; x ; s/[^\$AppServer1](AppServer1)/#\1/gi'

but the result is :

 #AppServer1:
      name: $#{AppServer1.name}
      ip: $#{AppServer1.ip}

what im missing here to comment the full string to be :

#AppServer1:
#      name: ${AppServer1.name}
#      ip: ${AppServer1.ip}
3 Answers

Using gnu-sed, you can do this:

sed '/^AppServer1/I{:a; /^[[:blank:]]*$/!{s/.*/#&/; n; ba;} }' file

some text here
some text here

#AppServer1:
#  name: ${AppServer1.name}
#  ip: ${AppServer1.ip}

some text here
some text here

AppServer2:
  name: ${AppServer1.name}
  ip: ${AppServer1.ip}

some text here
some text here

Details:

  • /^AppServer1/I: Search for AppServer1 case insensitive
  • {: Block start
    • :a: Make label a
    • /^[[:blank:]]*$/! If a line is not a blank line
    • {s/.*/#&/; n; ba;}: Prepend each line with #, read next line and goto label a
  • }: Block end

Using awk you can do this:

awk '/^AppServer1/ {b=1} b && !NF {b=0} b {$0 = "#" $0} 1' file

some text here
some text here

#AppServer1:
#  name: ${AppServer1.name}
#  ip: ${AppServer1.ip}

some text here
some text here

AppServer2:
  name: ${AppServer1.name}
  ip: ${AppServer1.ip}

some text here
some text here

A simpler sed solution might be this, if you're ok with having the final empty line commented too:

sed '/^AppServer1:/,/^[[:space:]]*$/s/^/# /' lines.txt 
some text here
some text here

# AppServer1:
#   name: ${AppServer1.name}
#   ip: ${AppServer1.ip}
# 
some text here
some text here

AppServer2:
  name: ${AppServer1.name}
  ip: ${AppServer1.ip}

some text here
some text here

It uses a sed range pattern, denoted by a comma (,). The start of the range is /^AppServer1:/, i.e., any line that starts (^) with AppServer1:. The end of the range is an empty line or one that contains only whitespace characters: /^[[:space:]]*$/, where ^: start of line; [[:space:]]*: zero or more (*) whitespace characters ([[:space:]]); $: end of line.

Next comes the [s]ubstitution command — s/^/# / — which substitutes the start of the line ^ with the sequence # on all lines within the matched range (inclusive end).

If you want a case-insensitive match, you need GNU sed. In that case you can add the I flag to the start-of-range pattern. This flag is not available on macOS sed, though.

Assuming the lines in your input that look empty truly are empty, you can do this using any awk in any shell on every Unix box:

$ awk -v RS= -v ORS='\n\n' '/^AppServer1:/{gsub(/^|\n/,"&#")} 1' file
some text here
some text here

#AppServer1:
#  name: ${AppServer1.name}
#  ip: ${AppServer1.ip}

some text here
some text here

AppServer2:
  name: ${AppServer1.name}
  ip: ${AppServer1.ip}

some text here
some text here
Related