Replace text between two lines with contents of a file stored in a variable in sed
This might work for you (GNU sed):
sed '/blue/,/gray/!b;//!d;/blue/r file2' file1
For the range of lines between blue
and gray
, delete lines that do not match either the first or the last lines in the range and read the lines to insert before the last line of the range.
EDIT:
The first sed command /blue/,/grey/!b
matches a range of lines i.e. the lines that range between a line containing blue
upto and including a line containing gray
. The !b
part means if the lines are not in that range then break out of the sed commands i.e. do not do any further sed processing for these lines, just print as normal.
The sed commands following will only affect those lines that are in the range between blue
and gray
.
The second command //!d
means: delete those lines that do not match either the start/end of the range i.e. blue
or gray
. The //
uses the regexp from a previous /.../
command. N.B. a delete command terminates any further sed processing for that line.
The sed commands following will only affect lines that containing either blue
or gray
.
The third command matches a line containing blue
and reads in lines from file2.
N.B. the lines containing blue
and grey
are processed by sed naturally and printed before the next line is read into the pattern space as are the lines not between blue
and gray
.
An alternative:
sed '/blue/,/gray/!b;//!d;/gray/e cat file2' file1
And another:
sed -ne '/blue/{p;r file2' -e ':a;n;/gray/!ba};p' file1
Linux: How to replace all text between two lines and substitute it with the output of a variable using sed?
You can probably use this sed
:
sed -e '/BEGIN/,/END/ {//!d; /BEGIN/r file.html' -e '}' file
This will insert content of file.html
file between BEGIN
and END
. To save changes back to file:
sed -i -e '/BEGIN/,/END/ {//!d; /BEGIN/r file.html' -e '}' file
Replace a word with multiple lines using sed?
If you build your multiple line text with "\n
"s, this will work with a simple sed
command as:
DATA=`echo ${DATA} | tr '\n' "\\n"`
#now, DATA="line1\nline2\nline3"
sed "s/_data_/${DATA}/" mail.tpl
Replace text between two strings in file using linux bash
EDITED:
Ok, if you want to retain the #start and #stop, I will revert to awk:
awk '
BEGIN {p=1}
/^#start/ {print;system("cat exceptions");p=0}
/^#end/ {p=1}
p' acl.txt
Thanks to @fedorqui for tweaks in comments below.
Output:
192.168.0.1
192.168.4.5
#start_exceptions
192.168.88.88
192.168.76.6
#end_exceptions
192.168.5.55
p is a flag that says whether or not to print lines. It starts at the beginning as 1, so all lines are printed till I find a line starting with #start. Then I cat the contents of the exceptions file and stop printing lines till I find a line starting with #end, at which point I set the p flag back to 1 so remaining lines get printed.
If you want output to a file, add "> newfile" to the very end of the command like this:
awk '
BEGIN {p=1}
/^#start/ {print;system("cat exceptions");p=0}
/^#end/ {p=1}
p' acl.txt > newfile
YET ANOTHER VERSION IF YOU REALLY WANT TO USE SED
If you really, really want to do it with sed, you can use nested address spaces, firstly to select the lines between #start_exceptions and #end_exceptions, then again to select the first line within that and also lines other than the #end_exceptions line:
sed '
/^#start/,/^#end/{
/^#start/{
n
r exceptions
}
/^#end/!d
}
' acl.txt
Output:
192.168.0.1
192.168.4.5
#start_exceptions
192.168.88.88
192.168.76.6
#end_exceptions
192.168.5.55
ORIGINAL ANSWER
I think this will work:
sed -e '/^#end/r exceptions' -e '/^#start/,/^#end/d' acl.txt
When it finds /^#end/ it reads in the exceptions file. And it also deletes everything between /#start/ and /#end/.
I have left the matching slightly "loose" for clarity of expressing the technique.
Replacing lines between two specific strings - sed equivalent in cmd
Use PowerShell, present from Windows 7 on.
## Q:\Test\2018\10\30\SO_53073481.ps1
## defining variable with a here string
$Text = @"
Many lines
many lines
they remain the same
[REPORT]
some text
some more text412
[TAGS]
text that I Want
to stay the same!!!
"@
$Text -Replace "(?sm)(?<=^\[REPORT\]`r?`n).*?(?=`r?`n\[TAGS\])",
"`nmy text goes here`nAnd a new line down here`n"
The -replace
regular expression uses nonconsuming lookarounds
Sample output:
Many lines
many lines
they remain the same
[REPORT]
my text goes here
And a new line down here
[TAGS]
text that I Want
to stay the same!!!
To read text from file, replace and write back (even without storing in a var) you can use:
(Get-Content ".\file.txt" -Raw) -Replace "(?sm)(?<=^\[REPORT\]`r?`n).*?(?=`r?`n\[TAGS\])",
"`nmy text goes here`nAnd a new line down here`n"|
Set-Content ".\file.txt"
The parentheses are neccessary to reuse the same file name in one pipe.
Sed command to change a string at only desired place
Is there any way to replace the string using a WHERE clause so I can replace the string only where I want?
sed
does not have SQL-style WHERE
clauses, but commands can have "addresses" that define subsets of input lines to operate upon. These can take several forms. Regular expressions are perhaps the most common, but there are also line numbers, and a couple of special forms. You can also have inclusive ranges built from simple addresses. An address range would be a reasonably good way to address the problem you present.
For example,
sed -i '/^\s*-\s*stage:\s*Moto_Dev/,/^\s*-/ s/dependsOn: Build/dependsOn: Test/' input
Explanation:
The
-i
command-line flag tellssed
to work "in-place", which really means that it will replace the original file with one containingsed
's output.The
/^\s*-\s*stage:\s*Moto_Dev/,/^\s*-/
is a range address, consisting of a regex for the range start (/^\s*-\s*stage:\s*MotoDev/
) and one for the range end (/^\s*-/
)./^\s*-\s*stage:\s*Moto_Dev/
matches the beginning of the section in which you want the change to be made, with some flexibility around the exact amount of whitespace at certain positions. For brevity and clarity, it uses\s
to represent a single space or tab character. That is a GNU extension, but if you cannot depend on GNUsed
then there are other ways to express the same thing./^\s*-/
matches the beginning of the next section, as you have presented the input. It could be made more specific if it were necessary to be more selective.
The range includes its endpoints, but that does not appear to be a problem for the task at hand.
There is only one such range in the input presented, and that range contains the line you want to modify. The specified substitution,
s/dependsOn: Build/dependsOn: Test/
, is performed on each line in the range, but only the one contains a match to be replaced. All others in the range will be unaffected.No commands at all are specified for lines outside the range, so they too will be unaffected.
You also asked,
I stored the desired piece of code in a variable. Can I use that
variable in ased
command? For example,sed -i "s/condition: succeeded('Fair_PreProd')/condition: succeeded('Fair_UAT')/g" $folder_path/$file_name
sed
does not expand shell-style parameter references, but you don't need it to do. The variable references in that command are expanded by the shell itself, before it executes the resulting command, so
- yes, you may use them, and
- it's not a question of using shell variables with
sed
in particular.
Related Topics
Escaping the Exclamation Point in Grep
How Come _Exit(0) (Exiting by Syscall) Prevents Me from Receiving Any Stdout Content
Shell Script Issue with Filenames Containing Spaces
Ada Compiler Crashes with "Ada Compiler Not Installed on This System." After Downgrading Gcc Version
Sched_Fifo Higher Priority Thread Is Getting Preempted by the Sched_Fifo Lower Priority Thread
How to Delete the Matching Pattern from Given Occurrence
Sort Command in Not Working Properly in Unix for Sorting a CSV File
Output File Not Created When Reading Sequences
Can't Find Unexpected Operator (Bash Error)
Sending Mail Body and Attachment Using Mailx - Linux
Replace Line with Space and Backslash with a String Containing Spaces
Bash - Calculate the Average of Numbers Inputted
Multiple -A with Greater Than/Less Than Break Bash Script
How to Prevent an X Window from Receiving User Input
File Glob Patterns in Linux Terminal
Stack Smashing Code Not Working on Linux Kernel 2.6.38.7... Please Help
Screen Command Disable the Control Key Ctrl-A to Use It in Vim
Segmentation-Fault Error Happening with Assembly Code Program