Final answer given more comments below and updated sample input/output in question:
I'd sort the data first so the act of filling in the missing values is more efficient and uses less memory than doing a 2-pass approach within awk and the final output is much better organized than the input was for readability:
$ cat tst.sh
#!/usr/bin/env bash
awk '
BEGIN { FS=OFS="\t" }
{ print (NR>1), ($4=="" ? $3 : $1), $4, $1, NR, $0 }
' "${@:--}" |
sort -t$'\t' -k1,1n -k2,2 -k3,3r -k4,4 -k5,5n |
cut -f6- |
awk '
BEGIN { FS=OFS="\t" }
$4 != "" { d = $2 }
$4 == "" { $4 = d }
{ print }
'
$ ./tst.sh file | column -s$'\t' -t
ID Designation ParentID ParentDesignation
A1 M.D-Sales 0 UmbrellaCorp
a1 Sr.Sales A1 M.D-Sales
a2 Jr.Sales A1 M.D-Sales
B1 M.D-R&D 0 UmbrellaCorp
b1 Sr.R&D B1 M.D-R&D
b2 Jr.SR&D B1 M.D-R&D
The first call to awk just decorates the input so it can be sorted by:
(NR>1)
= header-or-not 0-or-1 indicator to ensure the header line remains first after sorting,
($4=="" ? $3 : $1)
= the ID or ParentID for each row to group related rows together
$4
= the ParentDesignation so we can sort it such that rows with a ParentDesignation come before those that don't for the same ID/ParentID,
$1
= the ID so we can sort children alphabetically by their ID,
NR
= so if everything else is common we can print the lines in the same order as they occurred in the input (probably not necessary in this case as every ID appears to be unique but good practice for other similar situations).
Then we just sort
by the above fields and then remove the decorations using cut
before passing to the final awk
script to actually do the $4
population.
If you're not sure what any of those steps do, just change each |
to | cat; exit
one at a time and then you'll see what's happening at each step.
Previous answer:
Given the comments below, this might be what you want, assuming a parent (if it exists) always occurs before a child in your data:
$ cat tst.awk
BEGIN { FS=OFS="\t" }
$4 != "" {
id2des[$1] = $2
}
$4 == "" {
$4 = id2des[$3]
}
{ print }
$ awk -f tst.awk file
ID Designation ParentID ParentDesignation
A1 M.D-Sales 0 UmbrellaCorp
a1 Sr.Sales A1 M.D-Sales
a2 Jr.Sales A1 M.D-Sales
B1 M.D-R&D 0 UmbrellaCorp
b1 Sr.R&D B1 M.D-R&D
b2 Jr.SR&D B1 M.D-R&D
Original answer:
Your problem actually seems to be simpler than you specified as you appear to have a parent row with all info followed by children rows missing $4 in which case you don't need to look up anything, all you need is:
$ awk 'BEGIN{FS=OFS="\t"} $4!=""{d=$2} $4==""{$4=d} 1' file
ID Designation ParentID ParentDesignation
A1 M.D-Sales 0 UmbrellaCorp
a1 Sr.Sales A1 M.D-Sales
a2 Jr.Sales A1 M.D-Sales
B1 M.D-R&D 0 UmbrellaCorp
b1 Sr.R&D B1 M.D-R&D
b2 Jr.SR&D B1 M.D-R&D
$ awk 'BEGIN{FS=OFS="\t"} $4!=""{d=$2} $4==""{$4=d} 1' file | column -s$'\t' -t
ID Designation ParentID ParentDesignation
A1 M.D-Sales 0 UmbrellaCorp
a1 Sr.Sales A1 M.D-Sales
a2 Jr.Sales A1 M.D-Sales
B1 M.D-R&D 0 UmbrellaCorp
b1 Sr.R&D B1 M.D-R&D
b2 Jr.SR&D B1 M.D-R&D