SED Insert text after a specific multi-line text field - sed

I am looking to search for and add a new line of text after a specific multi-line text, in this example i need to add a space and text after "oldText" under "[old-text]" only:
[old-text]
oldText
[inserted-new-text]
newTxt
[alsoOld-text]
oldText
Here's what I have so far but the syntax is not correct:
printf "[old-text]\noldText"|sed '/\[old-text]\noldTex\t/a [inserted-new-text]\nnewTxt'

$ sed -e '/\[old-text\]/{N;s/oldText/&\n\n[inserted-new-text]\nnewTxt/}' inputFile
Use /<pattern>/ to find the [old-text] and then use N; to go to the next line and replace.
$ printf "[old-text]\noldText" | \
sed -e '/\[old-text\]/{N;s/oldText/&\n\n[inserted-new-text]\nnewTxt/}'
[old-text]
oldText
[inserted-new-text]
newTxt

Related

Extract substrings between strings

I have a file with text as follows:
###interest1 moreinterest1### sometext ###interest2###
not-interesting-line
sometext ###interest3###
sometext ###interest4### sometext othertext ###interest5### sometext ###interest6###
I want to extract all strings between ### .
My desired output would be something like this:
interest1 moreinterest1
interest2
interest3
interest4
interest5
interest6
I have tried the following:
grep '###' file.txt | sed -e 's/.*###\(.*\)###.*/\1/g'
This almost works but only seems to grab the first instance per line, so the first line in my output only grabs
interest1 moreinterest1
rather than
interest1 moreinterest1
interest2
Here is a single awk command to achieve this that makes ### field separator and prints each even numbered field:
awk -F '###' '{for (i=2; i<NF; i+=2) print $i}' file
interest1 moreinterest1
interest2
interest3
interest4
interest5
interest6
Here is an alternative grep + sed solution:
grep -oE '###[^#]*###' file | sed -E 's/^###|###$//g'
This assumes there are no # characters in between ### markers.
With GNU awk for multi-char RS:
$ awk -v RS='###' '!(NR%2)' file
interest1 moreinterest1
interest2
interest3
interest4
interest5
interest6
You can use pcregrep:
pcregrep -o1 '###(.*?)###' file
The regex - ###(.*?)### - matches ###, then captures into Group 1 any zero o more chars other than line break chars, as few as possible, and ### then matches ###.
o1 option will output Group 1 value only.
See the regex demo online.
sed 't x
s/###/\
/;D; :x
s//\
/;t y
D;:y
P;D' file
Replacing "###" with newline, D, then conditionally branching to P if a second replacement of "###" is successful.
This might work for you (GNU sed):
sed -n 's/###/\n/g;/[^\n]*\n/{s///;P;D}' file
Replace all occurrences of ###'s by newlines.
If a line contains a newline, remove any characters before and including the first newline, print the details up to and including the following newline, delete those details and repeat.

Replace one matched pattern with another in multiline text with sed

I have file with this text:
mirrors:
docker.io:
endpoint:
- "http://registry:5000"
registry:5000:
endpoint:
- "http://registry:5000"
localhost:
endpoint:
- "http://registry:5000"
I need to replace it with this text in POSIX shell script (not bash):
mirrors:
docker.io:
endpoint:
- "http://docker.io"
registry:5000:
endpoint:
- "http://registry:5000"
localhost:
endpoint:
- "http://localhost"
Replace should be done dynamically in all places without hard-coded names. I mean we should take sub-string from a first line ("docker.io", "registry:5000", "localhost") and replace with it sub-string "registry:5000" in a third line.
I've figure out regex, that splits it on 5 groups: (^ )([^ ]*)(:[^"]*"http:\/\/)([^"]*)(")
Then I've tried to use sed to print group 2 instead of 4, but this didn't work: sed -n 's/\(^ \)\([^ ]*\)\(:[^"]*"http:\/\/\)\([^"]*\)\("\)/\1\2\3\2\5/p'
Please help!
This might work for you (GNU sed):
sed -E '1N;N;/\n.*endpoint:.*\n/s#((\S+):.*"http://)[^"]*#\1\2#;P;D' file
Open up a three line window into the file.
If the second line contains endpoint:, replace the last piece of text following http:// with the first piece of text before :
Print/Delete the first line of the window and then replenish the three line window by appending the next line.
Repeat until the end of the file.
Awk would be a better candidate for this, passing in the string to change to as a variable str and the section to change (" docker.io" or " localhost" or " registry:5000") and so:
awk -v findstr=" docker.io" -v str="http://docker.io" '
$0 ~ findstr { dockfound=1 # We have found the section passed in findstr and so we set the dockfound marker
}
/endpoint/ && dockfound==1 { # We encounter endpoint after the dockfound marker is set and so we set the found marker
found=1;
print;
next
}
found==1 && dockfound==1 { # We know from the found and the dockfound markers being set that we need to process this line
match($0,/^[[:space:]]+-[[:space:]]"/); # Match the start of the line to the beginning quote
$0=substr($0,RSTART,RLENGTH)str"\""; # Print the matched section followed by the replacement string (str) and the closing quote
found=0; # Reset the markers
dockfound=0
}1' file
One liner:
awk -v findstr=" docker.io" -v str="http://docker.io" '$0 ~ findstr { dockfound=1 } /endpoint/ && dockfound==1 { found=1;print;next } found==1 && dockfound==1 { match($0,/^[[:space:]]+-[[:space:]]"/);$0=substr($0,RSTART,RLENGTH)str"\"";found=0;dockfound=0 }1' file

replace a line that contains a string with special characters

i want to replace lines which contains a string that has some special characters.
i used \ and \ for escape special characters but nothing changes in file.
i use sed like this:
> sed -i '/pnconfig\[\'dbhost\'\] = \'localhost\'/c\This line is removed.' tco.php
i just want to find lines that contains :
$pnconfig['dbhost'] = 'localhost';
and replace that line with:
$pnconfig['dbhost'] = '1.1.1.1';
Wrap the sed in double quotes as
sed -i "s/\(pnconfig\['dbhost'\] = \)'localhost'/\1'1.1.1.1'/" filename
Test
$ echo "\$pnconfig['dbhost'] = 'localhost';" | sed "s/\(pnconfig\['dbhost'\] = \)'localhost'/\1'1.1.1.1'/"
$pnconfig['dbhost'] = '1.1.1.1';
Use as below:
sed -i.bak '/pnconfig\[\'dbhost\'\] = \'localhost\'/pnconfig\[\'dbhost\'\] = \'1.1.1.1\'/' tco.php
Rather than modifying the file for the first time, create back up and then search for your pattern and then replace it with the other as above in your file tco.php
You don't have to worry about backslashing single quotes by using double quotes for sed.
sed -i.bak "/pnconfig\['dbhost'\] = 'localhost'/s/localhost/1.1.1.1/g" File
Try this one.
sed "/$pnconfig\['dbhost']/s/localhost/1.1.1.1/"

Wrap each line in a text file in apostrophes and add comma to end of lines

My actual text document contains the following lines.
san.20140226.sbc.UTM
san.201402261.UTM
san.2014022613.UTM
I want the below output:
'san.20140226.sbc.UTM',
'san.201402261.UTM',
'san.2014022613.UTM',
You could try this sed command,
sed "s/.*/'&',/g" file
Example:
$ echo 'san.20140226.sbc.UTM' | sed "s/.*/'&',/g"
'san.20140226.sbc.UTM',
OR
$ echo 'san.20140226.sbc.UTM' | sed "s/^/'/;s/$/',/"
'san.20140226.sbc.UTM',
^ matches the start of a line and $ matches the end of a line.

awk or sed replacing specific $3 with ajacent $2

File looks like
$1 $2 $3
Text Text2 *
Text Text4 Text3
I would like to search for *'s within a file and replace the with the text in the column next to it. While keeping the rest of the info... basicly replace the * logicaly with column 2.
Currently I am working with either sed or awk
awk : awk '{ if($3=*) {print$2}}' works... but I would like to keep $1,2 aswell
sed : sed -r 's/[*]//g' I can't get reg expression to replace with $2 properly
Any quick help, tips or tricks?
Contents of file.txt:
Text Text2 *
Text Text4 Text3
One way using awk:
awk '$3 == "*" { $3=$2 }1' file.txt
Results:
Text Text2 Text2
Text Text4 Text3
With GNU sed \S and \s can be used to represent non-space and space respectively, so you could accomplish what you want like this:
sed -r '/(\S+)\s+(\S+)\s+\*/ s//\1 \2 \2/'
The empty s/// command implicitly uses the matches from //.
If it is run on the input listed by steve:
sed -r '/(\S+)\s+(\S+)\s+\*/ s//\1 \2 \2/' file.txt
Output:
Text Text2 Text2
Text Text4 Text3
If you want to preserve inter-column whitespace use:
sed -r '/(\S+)(\s+)(\S+)(\s+)\*/ s//\1\2\3\4\3/'
awk solution:
awk '$3=="*"{$3=$2}1' file