0

I want to write a sed (or awk) command to replace a string from one file with the entire contents of another file. Note that second file from which I want to get the content has more than one line.

$ cat file.txt 
TEXT1 
TEST2 
TEST3 

and

$ cat other_file.txt 
there are multiple lines1 
there are multiple lines2 
there are multiple lines3 

And I want the output to be:

$ cat file3.txt
there are TEXT1 
TEST2 
TEST3 lines1

there are TEXT1 
TEST2 
TEST3 lines2

there are TEXT1 
TEST2 
TEST3 lines3

I tried this:

sed -i -e '/PLACEHOLDER/ r file' -e s/PLACEHOLDER// otherFile

But it didn't give me the right output.

replace "multiple" key word with all the content from file on each line hope this is clear

7
  • Doesn't look bad to me. What is your problem with your solution?
    – Philippos
    Jul 26, 2022 at 11:06
  • not giving me desired result
    – sam
    Jul 26, 2022 at 11:45
  • cat file.txt TEXT1 TEST2 TEST3 cat other_file.txt there are multiple lines1. there are multiple lines2. there are multiple lines3 I want output :- cat file3.txt there are TEXT1 TEST2 TEST3 lines1 there are TEXT1 TEST2 TEST3 lines2 there are TEXT1 TEST2 TEST3 lines3 replace "multiple" key word with all the content from file on each line hope this is clear
    – sam
    Jul 26, 2022 at 11:45
  • @user535186 please Edit the question. There is an "edit" link under the question, and you can also click on this edit link.
    – terdon
    Jul 26, 2022 at 11:46
  • 1
    @user535186 not the edit link under my answer, the one under your question: i.imgur.com/2sUnVDO.png
    – terdon
    Jul 26, 2022 at 11:49

3 Answers 3

0

Using the m4 macro processor, defining a macro called PLACEHOLDER which includes the other file:

$ cat file
foo PLACEHOLDER baz
$ cat otherfile
These are the
multi-line contents
of the other file.
$ m4 -D PLACEHOLDER='include(otherfile)' file
foo These are the
multi-line contents
of the other file.
 baz

Note that this includes the text from otherfile as-is, without stripping the final newline character.

4
  • Thanks however, not working ..no change in any file
    – sam
    Jul 26, 2022 at 10:51
  • 1
    @user535186 Well, write the output to a new file and then rename that new file to the original filename. You never mentioned how you wanted the result to be presented.
    – Kusalananda
    Jul 26, 2022 at 10:52
  • cat file.txt TEXT1 TEST2 TEST3 cat other_file.txt there are multiple lines1 there are multiple lines2 there are multiple lines3 I want output :- replace "multiple" key word with all the content from file
    – sam
    Jul 26, 2022 at 11:26
  • I'm afraid the OP wanted something very different as explained in an edit submitted to my answer. Please see updated question, it's a very different problem.
    – terdon
    Jul 26, 2022 at 11:55
0

Using any awk in any shell on every Unix box and given 1 possible interpretation of your requirements (that you want to do full-word string matching on space-separated "words", the replacement text might contain backreference metachars or other typically problematic chars, don't care about retaining white space, and that the target word could appear many times on a line):

$ cat tst.awk
BEGIN {
    ORS = RS RS
    old = "multiple"
}
NR==FNR {
    new = (NR>1 ? new RS : "") $0
    next
}
{
    for ( i=1; i<=NF; i++ ) {
        if ( $i == old ) {
            $i = new
        }
    }
    print
}

$ awk -f tst.awk file.txt other_file.txt
there are TEXT1
TEST2
TEST3 lines1

there are TEXT1
TEST2
TEST3 lines2

there are TEXT1
TEST2
TEST3 lines3
0

Using Raku (formerly known as Perl_6)

~$ raku -e 'my @a = dir(test => "Matsuo_Bashō.txt").IO.lines.join("\n"); for lines[0..9] { put S/e/@a[]/ };'  alphabet.txt
a
b
c
d
No one travels
Along this way but I,
This autumn evening.
f
g
h
i
j

Original_File being substituted == alphabet.txt

~$ raku -e 'for lines[0..9] { .put };' alphabet.txt
a
b
c
d
e
f
g
h
i
j

Second File to be inserted == Matsuo_Bashō.txt

~$ raku -e 'put dir(test => "Matsuo_Bashō.txt").IO.lines.join("\n");'
No one travels
Along this way but I,
This autumn evening.

Briefly, take the file you want to "insert" and read it in using Raku's dir() routine, storing it in the @a array. Then the second 'target' file (here an alphabetic sequence) is read-in off the command line. Raku will output the resultant string when substituted with the S/// "big-S" substitution operator. Note: the code above will only replace the first occurrence. To make this a global replacement (replacing all occurences of the recognition sequence e, add the :global adverb: S:global/// or more simply, S:g///.

There's no need to backslash @a in the replacement, simply add indexing square-brackets at the end: @a[] (curlies work also, see below).

If you don't want to substitute but instead want to insert a second file after a recognition sequence in the first, change the substitution operator to use a lookbehind assertion, and add a newline before the replacement:

{ put S/ <?after e> /\n@a[]/ }

#OR

{ put S/ <?after e> /\n{@a}/ }

Finally note that files can be slurped-in all at once. Using Raku's dir() routine that's:

  • dir(test => "Matsuo_Bashō.txt").IO.slurp;

...however an extra newline gets added to the output. You can use slurp and trim-trailing to replicate the answer above (below, a shorthand way of quoting the dir() filename string is to enclose it in angle brackets):

~$ raku -e 'my @a = dir(:test<Matsuo_Bashō.txt>).IO.slurp; for lines[0..9] { put S/e/{@a[].trim-trailing}/ };'  alphabet.txt

https://raku.org

0

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .