Skip to main content
added 1462 characters in body
Source Link
Stéphane Chazelas
  • 586.2k
  • 96
  • 1.1k
  • 1.7k

To store things, sed has a hold space and h/H commands to copy/append the pattern space to the host space (hold), g/G to get what's held and replace/append to the pattern space (and x to exchange hold and pattern space).

sed -E ' /^ {4}rtr-/h /snmp_location/{ s/$/\ \ routers:\ hosts:/ G }' 
sed -E ' /^ {4}rtr-/h /snmp_location/ { s/$/\ \ routers:\ hosts:/ G }' 

In a less antiquated language, thatthe equivalent would look like:

perl -pe ' $hold = $_ if /^ {4}rtr-/; $_ .= "\nrouters:\n hosts:\n$hold" if /snmp_location/' 
perl -pe ' $hold = $_ if /^ {4}rtr-/; $_ .= "\nrouters:\n hosts:\n$hold" if /snmp_location/' 

Or to avoid adding that routers section if rtr- was not found:

perl -pe ' $hold = $_ if /^ {4}rtr-/; $_ .= "\nrouters:\n hosts:\n$hold" if /snmp_location/ && defined $hold' 

In sed:

sed -E ' /^ {4}rtr-/h /snmp_location/ { G s/(\n)(.)/\1\1routers:\1 hosts:&/; t s/\n// }' 

Where we first append the hold space to the pattern space for lines that contain snmp_location, and only insert the routers section before what was appended if non-empty (matches .). Also note the then command that branches to the end if the substitution succeeded.

Note that if there are several occurrences of rtr- before the snmp_location line, all those will consider the last, not first. In perl you can change $host = to $host //= to skip the assignment if $hold is already defined. In sed, you could change it to:

sed -E ' /^ {4}rtr-/ { x /./ { # already found x b after_g } g : after_g } /snmp_location/ { G s/(\n)(.)/\1\1routers:\1 hosts:&/; t s/\n// }' 

Or, assuming the first occurrence of rtr- won't be on the first line (with GNU sed, you could replace 1 with 0 to cover for that case):

sed -E ' 1, /^ {4}rtr-/ { /^ {4}rtr-/ h } /snmp_location/ { G s/(\n)(.)/\1\1routers:\1 hosts:&/; t s/\n// }' 

To store things, sed has a hold space and h/H commands to copy/append the pattern space to the host space (hold), g/G to get what's held and replace/append to the pattern space.

sed -E ' /^ {4}rtr-/h /snmp_location/{ s/$/\ \ routers:\ hosts:/ G }' 

In a less antiquated language, that would look like:

perl -pe ' $hold = $_ if /^ {4}rtr-/; $_ .= "\nrouters:\n hosts:\n$hold" if /snmp_location/' 

To store things, sed has a hold space and h/H commands to copy/append the pattern space to the host space (hold), g/G to get what's held and replace/append to the pattern space (and x to exchange hold and pattern space).

sed -E ' /^ {4}rtr-/h /snmp_location/ { s/$/\ \ routers:\ hosts:/ G }' 

In a less antiquated language, the equivalent would look like:

perl -pe ' $hold = $_ if /^ {4}rtr-/; $_ .= "\nrouters:\n hosts:\n$hold" if /snmp_location/' 

Or to avoid adding that routers section if rtr- was not found:

perl -pe ' $hold = $_ if /^ {4}rtr-/; $_ .= "\nrouters:\n hosts:\n$hold" if /snmp_location/ && defined $hold' 

In sed:

sed -E ' /^ {4}rtr-/h /snmp_location/ { G s/(\n)(.)/\1\1routers:\1 hosts:&/; t s/\n// }' 

Where we first append the hold space to the pattern space for lines that contain snmp_location, and only insert the routers section before what was appended if non-empty (matches .). Also note the then command that branches to the end if the substitution succeeded.

Note that if there are several occurrences of rtr- before the snmp_location line, all those will consider the last, not first. In perl you can change $host = to $host //= to skip the assignment if $hold is already defined. In sed, you could change it to:

sed -E ' /^ {4}rtr-/ { x /./ { # already found x b after_g } g : after_g } /snmp_location/ { G s/(\n)(.)/\1\1routers:\1 hosts:&/; t s/\n// }' 

Or, assuming the first occurrence of rtr- won't be on the first line (with GNU sed, you could replace 1 with 0 to cover for that case):

sed -E ' 1, /^ {4}rtr-/ { /^ {4}rtr-/ h } /snmp_location/ { G s/(\n)(.)/\1\1routers:\1 hosts:&/; t s/\n// }' 
Source Link
Stéphane Chazelas
  • 586.2k
  • 96
  • 1.1k
  • 1.7k

To store things, sed has a hold space and h/H commands to copy/append the pattern space to the host space (hold), g/G to get what's held and replace/append to the pattern space.

sed -E ' /^ {4}rtr-/h /snmp_location/{ s/$/\ \ routers:\ hosts:/ G }' 

Would hold any line that starts with 4 spaces followed by rtr-, and for any line that contains snmp_location, would append those 3 extra literal lines (by substituting the end of it ($) with them), plus the contents of the hold space.

In a less antiquated language, that would look like:

perl -pe ' $hold = $_ if /^ {4}rtr-/; $_ .= "\nrouters:\n hosts:\n$hold" if /snmp_location/'