Unix code wanted to copy the template file and replace the lines in the template file in the copied files

I have 2 files:

File_1.txt:

John Mary Harry Bill 

File_2.txt:

 My name is ID, and I am on line NR of file 1. 

I want to create four files that look like this:

Output_file_1.txt:

 My name is John, and I am on line 1 of file 1. 

Output_file_2.txt:

 My name is Mary, and I am on line 2 of file 1. 

Output_file_3.txt:

 My name is Harry, and I am on line 3 of file 1. 

Output_file_4.txt:

 My name is Bill, and I am on line 4 of file 1. 

Normally for this purpose I would use the following sed command:

 for q in John Mary Harry Bill do sed 's/ID/'${q}'/g' File_2.txt > Output_file.txt done 

But this will only replace the ID for the name and will not contain the nr line of File_1.txt. Unfortunately, my bash skills are not much more than that ... Any tips or suggestions for a team that includes both files 1 and 2? I need to include file 1, because in fact the files are much larger than in this example, but I think I can understand the rest of the code if I know how to do this with this, hopefully a simpler example ... Many thanks in advance!

+4
source share
6 answers

What about:

 n=1 while read q do sed -e 's/ID/'${q}'/g' -e "s/NR/$n/" File_2.txt > Output_file_${n}.txt ((n++)) done < File_1.txt 

See the Bash Advanced Scripting Guide for redirecting input to blocks of code, and possibly the double brackets section for further reading.

+9
source

What about awk?

 [ ghoti@pc ~]$ cat file1 John Mary [ ghoti@pc ~]$ cat file2 Harry Bill [ ghoti@pc ~]$ cat merge.txt My name is %s, and I am on the line %s of file '%s'. [ ghoti@pc ~]$ cat doit.awk #!/usr/bin/awk -f BEGIN { while (getline line < "merge.txt") { fmt = fmt line "\n"; } } { file="Output_File_" NR ".txt"; printf(fmt, $1, FNR, FILENAME) > file; } [ ghoti@pc ~]$ ./doit.awk file1 file2 [ ghoti@pc ~]$ grep . Output_File*txt Output_File_1.txt:My name is John, and I am on the line 1 of file 'file1'. Output_File_2.txt:My name is Mary, and I am on the line 2 of file 'file1'. Output_File_3.txt:My name is Harry, and I am on the line 1 of file 'file2'. Output_File_4.txt:My name is Bill, and I am on the line 2 of file 'file2'. [ ghoti@pc ~]$ 

If you really want your file names to be numbered, we can do this too.

What's going on here?

The awk script BEGINS by reading in the merge.txt file and adding it to the "fmt" variable, line by line (separated by newline characters). This makes fmt format string compatible with printf.

Then, for each line in your input files (indicated on the command line), an output file is selected (NR is the current record count covering all files). The printf () function replaces every %s in the fmt variable with one of its options. The output is redirected to the appropriate file.

grep just shows you the entire contents of files with file names.

+3
source

This might work for you:

 sed '=' File_1.txt | sed '1{x;s/^/'"$(<File_2.txt)"'/;x};N;s/\n/ /;G;s/^\(\S*\) \(\S*\)\n\(.*\)ID\(.*\)NR\(.*\)/echo "\3\2\4\1\5" >Output_file_\1.txt/' | bash 
+1
source

TXR:

 $ txr merge.txr My name is John, and I am on the line 1 of file1. My name is Mary, and I am on the line 2 of file1. My name is Harry, and I am on the line 3 of file1. My name is Bill, and I am on the line 4 of file1. 

merge.txr:

 @(bind count @(range 1)) @(load "file2.txt") @(next "file1.txt") @(collect) @name @(template name @(pop count) "file1") @(end) 

file2.txt:

 @(define template (ID NR FILE)) @(output) My name is @ID, and I am on the line @NR of @FILE. @(end) @(end) 
+1
source
  • Read the names in the array.
  • get the length of the array
  • array iteration

Test preparation:

 echo "John Mary Harry Bill " > names 

Names and numbers:

 name=($(<names)) max=$(($(echo ${#name[*]})-1)) for i in $(seq 0 $max) ; do echo $i":"${name[i]}; done 

with template:

 for i in $(seq 0 $max) ; do echo "My name is ID, and I am on the line NR of file 1." | sed "s/ID/${name[i]}/g;s/NR/$((i+1))/g"; done My name is John, and I am on the line 1 of file 1. My name is Mary, and I am on the line 2 of file 1. My name is Harry, and I am on the line 3 of file 1. My name is Bill, and I am on the line 4 of file 1. 
+1
source

A slight modification needed for your script.Thats it.

 pearl.306> cat temp.sh #!/bin/ksh count=1 cat file1|while read line do sed -e "s/ID/${line}/g" -e "s/NR/${count}/g" File_2.txt > Output_file_${count}.txt count=$(($count+1)) done pearl.307> pearl.303> temp.sh pearl.304> ls -l Out* -rw-rw-r-- 1 nobody nobody 59 Mar 29 18:54 Output_file_1.txt -rw-rw-r-- 1 nobody nobody 58 Mar 29 18:54 Output_file_2.txt -rw-rw-r-- 1 nobody nobody 58 Mar 29 18:54 Output_file_3.txt -rw-rw-r-- 1 nobody nobody 58 Mar 29 18:54 Output_file_4.txt -rw-rw-r-- 1 nobody nobody 58 Mar 29 18:54 Output_file_5.txt pearl.305> cat Out* My name is linenumber11, and I am on the line 1 of file 1. My name is linenumber2, and I am on the line 2 of file 1. My name is linenumber1, and I am on the line 3 of file 1. My name is linenumber4, and I am on the line 4 of file 1. My name is linenumber6, and I am on the line 5 of file 1. pearl306> 
+1
source

Source: https://habr.com/ru/post/1403984/


All Articles