Skip to content

Instantly share code, notes, and snippets.

@StudioEtrange
Last active November 18, 2021 21:03
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save StudioEtrange/152e7bd0ac278b175663d11ab5db5d81 to your computer and use it in GitHub Desktop.
Save StudioEtrange/152e7bd0ac278b175663d11ab5db5d81 to your computer and use it in GitHub Desktop.
Awk function that can in any text or configuration file substitute a key with its own value, if its value is assigned earlier in the file
# In any text or configuration file substitute a key with its own value, if its value is assigned earlier in the file and the key is referenced with {{key}}
# This could be used on any text file, i.e an .ini file or a docker-compose env file
# The mechanism works like in shell script variable syntax in some ways : assignation, declaration, resolution order and comment symbol (#)
# Usage : substitute_key_in_file "<file_path>"
# Input file content:
# N=10
# The number is {{N}}
# # FOO={{N}}
# A=1
# B={{A}}
# C={{B}}
# X={{Y}}
# Y=4
# X={{Y}}
# Result file content:
# N=10
# # The number is 10
# # FOO=10
# A=1
# B=1
# C=1
# X={{Y}}
# Y=4
# X=4
substitute_key_in_file() {
local _file="$1"
local _temp=$(mktmp)
awk -F= '
function parsekey(str) {
# if there is a value assignation to a key into this string
# update val array
if (match(str,/^([^=#]*)=(.*)/,tmp)) {
val[tmp[1]]=tmp[2];
}
}
# fill the key array which contains all existing key
/^[^=#]*=/ {
# FNR=NR only when reading first file
if (FNR==NR) {
key[$1]=1;
next;
}
}
/.*/ {
# FNR=NR only when reading first file
if (FNR==NR) {
next;
}
}
# this block is triggered at each line only if not bypassed by next
# so this block is really triggered only when reading second file
{
for (k in key) {
# transform any reference to the keyy in current line into its value, if it has a known value
# key[] list all existing keys in file
# val[] list only key which have a known value
if (k in val) {
# we replace any reference to the key with its value with gsub in current line
gsub("{{"k"}}", val[k]);
}
}
# re-parse the current line to find any value assignation to a key
parsekey($0);
print $0;
}
' "${_file}" "${_file}" > "${_temp}"
cat "${_temp}" > "${_file}"
rm -f "${_temp}"
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment