Using sed to add text after a pattern, but the added text comes from a list file
In the following I present an almost pure sed
solution.
sed
has an r
command to read files, so you could in principle use that to read the file2
. However, no subsequent command will affect the lines read from the file, so I cannot think of any way of using the r
command effectively to do what you ask.
However, a solution is possible if file1
and file2
are both given in input to sed
.
In the following, in order to distinguish the two files, I put a marker line (-----
) that I give for granted is not in file2
; it could be anywhere in file1
without creating any problems, however.
cat file2 <(echo '-----') file1 | sed -f script.sed
where script.sed
is the following:
1{ # only on line 1 :a # begin while /-----/!{ # while the line does not contain the marker N # append the following line ba # end while } # here the pattern space is a multiline containing the list s/\n-----// # remove the last newline and the marker h # put the multiline in the hold space d # delete, as we don't want to print anything so far} # that's it, lines from 1 to the marker are processed/stash\/scm\//{ # for lines matching this pattern G # we append the full hold space s/'\n\([^\n]*\)/\1'/ # and position the first entry in the list appropriately x # then we swap pattern and hold space s/[^\n]*\n// # remove the first element of the list x # and swap again} # now the hold space has one item less
This is a bash
script that uses sed
and reads File_2 (The file containing the replacements) line by line, thus reading one replacement at a time. I then replaced the lines in File_1 with a sed script.
while IFS= read -r line; do sed -i "0,/\/stash\/scm\/'/{s|/stash/scm/'|/stash/scm/${line}'|}" File_1.txtdone < File_2.txt
Some tricks used to do this:
sed '0,/Apple/{s/Apple/Banana/}' input_filename
Replace only the first occurrence in filename of the stringApple
with the stringBanana
- Using double quotes for the
sed
script to allow for variable expansion${line}
- Making sure the search string to replace was being changed each iteration. This was done by including the ending single quote char
'
for the search argument in the sed scripts|/stash/scm/'|
- Reading a file line by line in a bash script
while IFS= read -r line; do echo $linedone < File_2.txt
You want to have lines like
sed 's#'/stash/scm/'#&something_from_file2#' file1
You can make these lines with
# Note: # / is not a delimiter, but part of the path # % is the delimiter in the current sed-command # # is the delimiter in the generated command.sed 's%.*%s#/stash/scm/#\&&#%' file2
You can generate these commands on the fly and execute them on file1.
sed -f <(sed 's%.*%s#/stash/scm/#\&&#%' file2) file1
One problem left. Both commands will substitute all matches.
I will use the single quote given after the match.When something is put before the single quote in /stash/scm/'
this is different than the match files when you look for the /stash/scm/'
string including the quote.
You want to generate lines like
s#(/stash/scm/)(')#\1randomRepo.git\2#s#(/stash/scm/)(')#\1differentRandomRepo.git\2#
Each substition should be done only once, so we consider file2 as one long line using the option -z
:
sed -rzf <(sed 's%.*%s#(/stash/scm/)('\'')#\\1&\\2#%' file2) file1