108 lines
1.7 KiB
Bash
Executable File
108 lines
1.7 KiB
Bash
Executable File
#!/bin/sh
|
|
set -eu
|
|
|
|
INPUT="${1:?input file required}"
|
|
OUTPUT="${2:?output file required}"
|
|
|
|
mkdir -p "$(dirname "$OUTPUT")"
|
|
|
|
TMP="$(mktemp)"
|
|
BASE_CREATED=0
|
|
|
|
if [ -f "$OUTPUT" ]; then
|
|
BASE="$OUTPUT"
|
|
else
|
|
BASE="$(mktemp)"
|
|
BASE_CREATED=1
|
|
: > "$BASE"
|
|
fi
|
|
|
|
cleanup() {
|
|
rm -f "$TMP"
|
|
if [ "$BASE_CREATED" = "1" ]; then
|
|
rm -f "$BASE"
|
|
fi
|
|
}
|
|
trap cleanup EXIT INT TERM
|
|
|
|
awk '
|
|
function trim(s) {
|
|
sub(/^[[:space:]]+/, "", s)
|
|
sub(/[[:space:]]+$/, "", s)
|
|
return s
|
|
}
|
|
|
|
function parse_key(line, eq, key) {
|
|
eq = index(line, "=")
|
|
if (eq == 0) {
|
|
return ""
|
|
}
|
|
|
|
key = trim(substr(line, 1, eq - 1))
|
|
|
|
if (key !~ /^[A-Za-z_][A-Za-z0-9_]*$/) {
|
|
return ""
|
|
}
|
|
|
|
return key
|
|
}
|
|
|
|
function merged_line(key, line) {
|
|
if (key ~ /^MKS_/ && key in ENVIRON) {
|
|
return key "=" ENVIRON[key]
|
|
}
|
|
|
|
return line
|
|
}
|
|
|
|
# First file: INPUT
|
|
phase == 1 {
|
|
line = $0
|
|
key = parse_key(line)
|
|
|
|
if (key != "") {
|
|
incoming[key] = merged_line(key, line)
|
|
|
|
if (!(key in input_seen)) {
|
|
input_order[++input_count] = key
|
|
input_seen[key] = 1
|
|
}
|
|
}
|
|
|
|
next
|
|
}
|
|
|
|
# Second file: existing OUTPUT / BASE
|
|
phase == 2 {
|
|
line = $0
|
|
key = parse_key(line)
|
|
|
|
if (key != "" && key in incoming) {
|
|
print incoming[key]
|
|
written[key] = 1
|
|
next
|
|
}
|
|
|
|
print line
|
|
|
|
if (key != "") {
|
|
written[key] = 1
|
|
}
|
|
|
|
next
|
|
}
|
|
|
|
END {
|
|
for (i = 1; i <= input_count; i++) {
|
|
key = input_order[i]
|
|
|
|
if (!(key in written)) {
|
|
print incoming[key]
|
|
written[key] = 1
|
|
}
|
|
}
|
|
}
|
|
' phase=1 "$INPUT" phase=2 "$BASE" > "$TMP"
|
|
|
|
mv "$TMP" "$OUTPUT"
|