1

I want to replace the column in a line with some keys in a file

for val in "${keyarr[@]}";
do
    while read dataline <&3 && read keyline <&4; do
        echo $dataline |
        awk -F $ifs -v col=$val -v line=$keyline '{
            $col=line; print $0 ;} ' OFS=$ifs > sourcedata1
    done 3<sourcedata1 4<keysnotfound
done

val is the column number that I want to replace with a key.

So I may have multiple columns to replace.

This solution does not work. how can I replace multiple columns with the keys all at once.

for example I fetch a line from sourcedata1

101, 102, 103 , 104

and from keynotfound in the while loop

105

And at the first iteration of for loop val = 1

then I want to replace 1st column of the dataline with the key

105, 102, 103, 104

and same for the second iteration if val = 3.

105, 102, 105, 104

Instead of using for loop, I want a solution in AWK or SED itself and it should update the source file with keys in multiple column.

Aman Singh Rajpoot
  • 1,451
  • 6
  • 26
  • The immediate problem is probably because of the [incorrect (lack of) quoting](https://stackoverflow.com/questions/10067266/when-to-wrap-quotes-around-a-shell-variable); but repeatedly looping over the same two files seems grossly inefficient and inelegant. What's in `keyarr`? All of this should probably be refactored to a single Awk script but it's hard to say exactly how without seeing the input data. – tripleee May 01 '21 at 09:52
  • Ya, I found out and corrected it, but still need a solution to update all the keys in the same line. – Aman Singh Rajpoot May 01 '21 at 10:14

1 Answers1

0

Your problem statement is rather obscure, but I'm guessing something like this refactoring should do what you are trying to ask.

Instead of loop over the same files, and rewriting one of them, just pass in the array of column indices, and read the files just once.

cols=$(printf '%s;' "${keyarr[@]}")
awk -F "$ifs" -v c="${cols%;}" 'BEGIN { split(c, cols, ";"); OFS=IFS }
    NR==FNR { repl[FNR] = $0; next }
    { for(col in cols) $col = repl[FNR] }' keysnotfound sourcedata1

The Awk idiom NR==FNR { ...; next } is a common way to read the first input file into memory (because the overall input line number NR is equal to the line number within the current file FNR). We read the entries from keysnotfound into repl which is indexed by the line number. With that, we can fall through and process the second file, where we loop over the column indices, and replace each one with the value we collected from the first file for this line number.

tripleee
  • 175,061
  • 34
  • 275
  • 318