You could also try something like this:
#!/bin/ksh
awk -v abbrev="${2:-ab}" '
# Process 1st file (lookup.txt)...
FNR == NR {
if(NR > 1) { # Skip over heading in file lookup.txt.
# Build the arrays a[abbreviation, id] = name for the 1st
# abbreviation found for a given id, and n2id[name] = id for all
# names.
if(!(((ab = substr($1, 1, match($1, /[[:digit:]]/) - 1)), $2) in a))
a[ab, $2] = $1
n2id[$1] = $2
#printf("in=%s, n2id[%s]=%s, a[%s,%s]=%s\n", $0, $1, n2id[$1], ab, $2, a[ab,$2])
}
next
}
# Process 2nd file (1st script operand)...
(abbrev, n2id[$1]) in a {
$1 = a[abbrev, n2id[$1]]
}
# Print original or converted input line...
1' lookup.txt "${1:-list.txt}"
This was written and tested using the Korn shell, but will also work with any other shell that performs POSIX standard variable expansions (such as bash , ash , or dash ).
If you want to try this on a Solaris/SunOS system, change awk to /usr/xpg4/bin/awk , /usr/xpg6/bin/awk , or nawk .
It is intended to be invoked with two operands, but if only one operand (specifying the list file to be used) is provided, the abbreviation defaults to "ab"; and if no operands are provided, the list file defaults to "list.txt" and the abreviation defaults to "ab".
(If you uncomment the printf statement, you can watch it build the arrays it will be using as it reads lookup.txt.)
With your sample input, the output produced when it is invoked as:
./lookup.sh list.txt ab
or
./lookup.sh
is:
ab1
ab2
er3
and when invoked as:
./lookup.sh list.txt fgh
it produces the output:
fgh1
fg21
fgh5