Reading multiple lines using read line do

Viewed 131

OK i'm an absolute noob to this (only started trying to code a few weeks ago for my job) so please go easy on me IM on an aix system I have file1, file2 and file3 and they all contain 1 column of data (text or numerical).

file1
VBDSBQ_KFGP_SAPECC_PRGX_ACCNT_WKLY
VBDSBQ_KFGP_SAPECC_PRGX_ADDRM_WKLY
VBDSBQ_KFGP_SAPECC_PRGX_COND_WKLY
VBDSBQ_KFGP_SAPECC_PRGX_CUSTM_WKLY
VBDSBQ_KFGP_SAPECC_PRGX_EPOS_DLY
VBDSBQ_KFGP_SAPECC_PRGX_INVV_WKLY

file2
MCMILS03
HGAHJK05
KARNEK93
MORROT32
LAWFOK12
LEMORK82


file3
8970597895
0923875
89760684
37960473
526238495
146407

There will be the exact same amount of lines in each of these files. I have another file called "dummy_file" which is what i want to pull out, replace parts and pop into a new file.

WORKSTATION#JOB_NAME
SCRIPTNAME "^TWSSCRIPTS^SCRIPT"
STREAMLOGON "^TWSUSER^"
-job JOB_NAME -user USER_ID -i JOB_ID
RECOVERY STOP

There are only 3 strings i care about in this file that i want replaced and they will always be the same for the dummy files i use in future

JOB_NAME
JOB_ID
USER_ID

There are 2 entries for JOB_NAME and only 1 for the others. What i want is take the raw file, replace both JOB_NAME entries with line 1 from file1 then replace USER_ID with line 1 from file 2 and then replace JOB_ID with line 1 from file3 then throw this into a new file I want to repeat the process for all the lines in file 1, 2 and 3 so the next one will have its entries replaced by line 2 from the 3 files then next one will have its entries replaced by line 3 from the 3 files then all of line 3 from the files and so on and so on

raw file and the expected output are below:

WORKSTATION#JOB_NAME
SCRIPTNAME "^TWSSCRIPTS^SCRIPT"
STREAMLOGON "^TWSUSER^"
-job JOB_NAME -user USER_ID -i JOB_ID
RECOVERY STOP



WORKSTATION#VBDSBQ_KFGP_SAPECC_PRGX_ACCNT_WKLY
SCRIPTNAME "^TWSSCRIPTS^SCRIPT"
STREAMLOGON "^TWSUSER^"
-job VBDSBQ_KFGP_SAPECC_PRGX_ACCNT_WKLY -user MCMILS03 -i 8970597895
RECOVERY STOP

this is as far as i got (again i know its crap)

file="/dir/dir/dir/file1"

while IFS= read -r line
do
cat dummy_file | sed "s/JOB_NAME/$file1/" | sed "s/JOB_ID/$file2/" | sed "s/USER_ID/$file3"  #####this is where i get stuck as i dont know how to reference file2 and file3##### >>new_file.txt
done
4 Answers

You really don't want a do/while loop in the shell. Just do:

awk '/^WORKSTATION/{
    getline jobname < "file1"; 
    getline user_id < "file2"; 
    getline job_id < "file3"
    }
    { 
    gsub("JOB_NAME", jobname); 
    gsub("USER_ID", user_id); 
    gsub("JOB_ID", job_id)
    }1'  dummy_file

This might work for you (GNU parallel and sed):

parallel -q sed 's/JOB_NAME/{1}/;s/USER_ID/{2}/;s/JOB_ID/{3}/' templateFile >newFile :::: file1 ::::+ file2 ::::+ file3

This creates newFile by appending the templateFile for each instance of a line jointly in file1, file2 and file3.

N.B. the ::::+ operation ensures the union of lines in file1, file2 and file3 rather than the default product.

Using GNU awk (ARGIND and 2d arrays):

$ gawk '
NR==FNR {                              # store the template file
    t=t (t==""?"":ORS) $0              # to t var
    next
}
{
    a[FNR][ARGIND]=$0                  # store filen records to 2d array
}
END {                                  # in the end
    for(i=1;i<=FNR;i++) {              # for each record stored from filen
        t_out=t                        # make a working copy of the template
        gsub(/JOB_NAME/,a[i][2],t_out) # replace with data
        gsub(/USER_ID/,a[i][3],t_out)
        gsub(/JOB_ID/,a[i][4],t_out)
        print t_out                    # output
    }
}' template file1 file2 file3

Output:

WORKSTATION#VBDSBQ_KFGP_SAPECC_PRGX_ACCNT_WKLY
SCRIPTNAME "^TWSSCRIPTS^SCRIPT"
STREAMLOGON "^TWSUSER^"
-job VBDSBQ_KFGP_SAPECC_PRGX_ACCNT_WKLY -user MCMILS03 -i 8970597895
RECOVERY STOP
...

Bash variant

#!/bin/bash

exec 5<file1 # create file descriptor for file with job names
exec 6<file2 # create file descriptor for file with job ids
exec 7<file3 # create file descriptor for file with user ids
dummy=$(cat dummy_txt) # load dummy text

output () { # create output by inserting new values in a copy of dummy var
    out=${dummy//JOB_NAME/$JOB_NAME}
    out=${out//USER_ID/$USER_ID}
    out=${out//JOB_ID/$JOB_ID}
    printf "\n$out\n"
}

while read -u5 JOB_NAME; do # this will read from all files and print output
      read -u6 JOB_id
      read -u7 USER_ID
      output
done

From read help

$ read --help
      ...
      -u fd read from file descriptor FD instead of the standard input
      ...

And a variant with paste

#!/bin/bash
dummy=$(cat dummy)
while read JOB_NAME JOB_id USER_ID; do
    out=${dummy//JOB_NAME/$JOB_NAME}
    out=${out//USER_ID/$USER_ID}
    out=${out//JOB_ID/$JOB_ID}
    printf "\n$out\n"
done < <(paste file1 file2 file3)
Related