Reputation: 6136
I've got two properties files and I'd like to replace key/value pairs in File A with any matching key/value entries in File B. File A will have more entries than File B - it's not expected that the two files will have the exact same number of entries. Also, File B might have entries which are not included in File A.
As an example:
File A
"GB" = "United Kingdom";
"SE" = "Sweden";
"BR" = "Brazil";
"FR" = "France";
"ES" = "Spain";
"DE" = "Germany";
File B
"GB" = "Regno Unito";
"SE" = "Svezia";
"BR" = "Brasile";
"BR" = "Brasile";
"CL" = "Cile";
Desired Result
"GB" = "Regno Unito";
"SE" = "Svezia";
"BR" = "Brasile";
"FR" = "France";
"ES" = "Spain";
"DE" = "Germany";
"CL" = "Cile";
Is it possible to execute this search and replace using bash?
Thanks,
Sean
Upvotes: 0
Views: 535
Reputation: 54512
Here's one way using GNU awk
:
awk -F " = " 'FNR==NR { array[$1]=$2; next } $1 in array { sub ($2, array[$1]) }1' fileb filea
Results:
"GB" = "Regno Unito";
"SE" = "Svezia";
"BR" = "Brasile";
"FR" = "France";
"ES" = "Spain";
"DE" = "Germany";
EDIT:
You can simply delete the array elements after a substitution has occurred. Then at the end of the script, print out what's left:
awk -F " = " 'FNR==NR { array[$1]=$2; next } $1 in array { sub ($2, array[$1]); delete array[$1] }1; END { for (i in array) print i FS array[i] }' fileb filea
Results:
"GB" = "Regno Unito";
"SE" = "Svezia";
"BR" = "Brasile";
"FR" = "France";
"ES" = "Spain";
"DE" = "Germany";
"CL" = "Cile";
Upvotes: 2
Reputation: 46856
The following bash-only script will spit out the results you're asking for:
#!/bin/bash
# Identify our files. If you want, test for their existence before proceeding.
fileA="$1"
fileB="$2"
# Define an associated array
declare -A countries
# Read our initial data
while read cc junk name; do
if [[ -n "$cc" ]]; then
countries["$cc"]="$name"
fi
done < "$fileA"
# Overwrite array elements with updated values
while read cc junk name; do
if [[ -n "$cc" ]]; then
countries["$cc"]="$name"
fi
done < "$fileB"
# Print the results
for cc in "${!countries[@]}"; do
echo "$cc = ${countries[$cc]}"
done
The results won't be in exactly the same order, but I suspect that isn't important. If it is, you can create an additional array whose index is a counter, then instead of the final for cc in ...
, you can simply walk through that array to get the $countries
indices in the right order. Let me know if that's important and you can't figure it out.
I only post this here because you asked for a bash solution. Steve's awk
script is much more succinct, and probably a lot faster. (Just guessing. It probably isn't even worth the time to benchmark it.)
Upvotes: 1