Find Matching Text and Replace Next Line

find matching text and replace next line

This might work for you (GNU sed):

sed '/<key>ConnectionString<\/key>/!b;n;c<string>changed_value</string>' file

!b negates the previous address (regexp) and breaks out of any processing, ending the sed commands, n prints the current line and then reads the next into the pattern space, c changes the current line to the string following the command.

Find a matching text and replace next two lines in unix

With GNU sed:

sed '/bbb/,+2{ /bbb/b; s/.*/zzz/ }' file

With awk:

awk '/bbb/{print; getline; print "zzz"; getline; print "zzz"; next}1' file

find matching text and replace next line in yml

sed is best for s/old/new, that is all. For anything else just use awk for clarity, portability, robustness, etc. Look:

$ awk -v rec='applicationConnectors' -v tag='port' -v val='14081' '
/^ [^ ]/{name=$1} name==(rec":") && $1==(tag":"){sub(/[^ ]+$/,""); $0=$0 val}
1' file
applicationConnectors:
- type: http
port: 14081
bindHost: 15.213.48.154
headerCacheSize: 512 bytes
outputBufferSize: 32KiB
maxRequestHeaderSize: 8KiB
maxResponseHeaderSize: 8KiB
inputBufferSize: 8KiB
idleTimeout: 30 seconds
minBufferPoolSize: 64 bytes
bufferPoolIncrement: 1KiB
maxBufferPoolSize: 64KiB
acceptorThreads: 1
selectorThreads: 2
acceptQueueSize: 1024
reuseAddress: true
useServerHeader: false
useDateHeader: true
useForwardedHeaders: true

adminConnectors:
- type: http
port: 14180

Want to change acceptQueueSize: to 17 instead? It's the same script with just different variable values:

$ awk -v rec='applicationConnectors' -v tag='acceptQueueSize' -v val='17' '
/^ [^ ]/{name=$1} name==(rec":") && $1==(tag":"){sub(/[^ ]+$/,""); $0=$0 val}
1' file
applicationConnectors:
- type: http
port: 14080
bindHost: 15.213.48.154
headerCacheSize: 512 bytes
outputBufferSize: 32KiB
maxRequestHeaderSize: 8KiB
maxResponseHeaderSize: 8KiB
inputBufferSize: 8KiB
idleTimeout: 30 seconds
minBufferPoolSize: 64 bytes
bufferPoolIncrement: 1KiB
maxBufferPoolSize: 64KiB
acceptorThreads: 1
selectorThreads: 2
acceptQueueSize: 17
reuseAddress: true
useServerHeader: false
useDateHeader: true
useForwardedHeaders: true

adminConnectors:
- type: http
port: 14180

Only try that with your currently accepted sed solution if you enjoy counting ns :-). Note also that this will work no matter what order the lines appear within each record since it keys off the name port rather than assuming that will appear some specific number of lines after applicationConnectors:. Finally, this will work even if the strings you're searching for or replacing with contain RE metachars (e.g. .), backreference chars (e.g. \1 or &), or sed delimiters (e.g. /).

Bash: Find matching text and replace next line

Your NEW_FILE is probably a bash-variable and therefore not a variable in awk. So, either let bash do the expansion:

awk '/working/ { print; print "'$NEW_FILE'"; next}1' test1.txt

or pass/set the variable from the command line:

awk -v NEW_FILE="$NEW_FILE" '/working/ { print; print NEW_FILE; next}1' test1.txt

How to replace 2 consecutive lines after Match with Sed

gnu and some other sed versions allow you to grab a range using relative number so you can simply use:

sed -E '/^#ABC$/,+2 s/(Size=)bar/\1foo/' file
#ABC
oneSize=foo
twoSize=foo
threeSize=foo

Command details:

  • /^#ABC$/,+2 Match range from pattern #ABC to next 2 lines
  • s/(Size=)bar/\1foo/: Match Size=bar and replace with Size=foo, using a capture group to avoid repeat of same String in search and substitution

You may also consider awk to avoid repeating pattern and replacements N times if you have to replace N lines after matching pattern:

awk 'n-- {sub(/Size=bar/, "Size=foo")} /^#ABC$/ {n=2} 1' file

#ABC
oneSize=foo
twoSize=foo
threeSize=foo

Find and replace text containing a new line

In general you can used sed -z which tells sed to use the null-character to split lines. Assume you have the file text containing

Hello World
This is a line
line1
line2
Hello World, again
line1
line2
end

Executing sed -z -e 's/line1\nline2/xxx/g' text yields

Hello World
This is a line
xxx
Hello World, again
xxx
end

You can add * (that is <space><star>) to handle inconsistent white spaces.


In your specific case if you want to delete the second line you can use a block statement to advance to the next line and delete it if it matches the second line

sed -e '/line1/{n;/line2/d}' text

Replace next N lines before a first/second/third/... match including the match

Here's a BSD sed version (comment.sed):

/Text/, /}/ {
s|^|//|
/}/ {
:idle
n
b idle
}
}

The first line /Text/, /}/ is a regex address range. Every line within that that range (inclusive) will be commented out. At the end of this range, the second /}/, we loop back to the idle label consuming the rest of the file. Otherwise the address range would also comment out the second Text block.

A one line version:

sed '/Text/, /}/ {s|^|//|; /}/ {:idle; n; b idle}}' input

To test:

diff expect <(sed -f comment.sed input) && echo ok

Replace text in file if previous line matches another text

One way to do it with sed (tested using macOS's sed and GNU sed), would be this:

replace.sed

#!/usr/bin/env sed -Ef

/FooBarB/,/^FooBar/ {
s/(foo[[:space:]]*=[[:space:]]*).+/\1new-value/
}

Here's what it does:

  1. /FooBarB/,/^FooBar/ matches a range of lines where the first line matches the regex /FooBarB/ and the last line matches the regex /^FooBar/ (which is the start of the next "group"). The comma between the two regexes is the syntax for range matching in sed.

  2. s/(foo[[:space:]]*=[[:space:]]*).+/\1new-value/ — [s]ubstitutes (in the matched range of lines) whatever matches the regex (foo[[:space:]]*=[[:space:]]*).+ with \1new-value, where \1 references the first capturing group in the search regex. The search regex looks for foo followed by optional whitespace, followed by an = sign, followed again by whitespace and then whatever else is there, which in your case is the old value.

You could do it all in just one line, but I wanted to show a version that's a bit more digestible (as far as sed goes, in any case):

sed -E '/FooBarA/,/^FooBar/s/(foo[[:space:]]*=[[:space:]]*).+/\1new-value/' temp.md 


Related Topics



Leave a reply



Submit