Eric Renouf estava certo, bash provavelmente não é a melhor ferramenta para isso; mas isso não me impediu de tentar!
O script a seguir usa um monte de bash-isms para fazer seu trabalho:
-
mapfile
para ler o arquivo de entrada (na matriz MAPFILE padrão), cortando as novas linhas ( -t
)
-
expressão condicional interna [[
cuja única finalidade é encontrar linhas do arquivo de conversão que se pareçam com pares chave = valor. A expressão regular deseja ver pelo menos um caractere para uma chave e um para um valor.
-
cria uma variável expr
para usar como expressão sed.
O script bash:
#!/usr/bin/env bash
# Usage: $0 [input file] [translation file] [output file]
mapfile -t < "$2"
expr=""
for keyvalue in "${MAPFILE[@]}"
do
if [[ $keyvalue =~ (.+)=(.+) ]]
then
k="${BASH_REMATCH[1]}"
v="${BASH_REMATCH[2]}"
expr="$expr s/\[\[$k\]\]/$v/g;"
fi
done
sed "$expr" "$1" > "$3"
Se eu fosse dedicado, usaria o mapfile novamente no arquivo de entrada, executaria o loop na matriz de conversão MAPFILE e usaria a expansão ${parameter/pattern/string}
em cada linha de entrada para gravar um novo arquivo de saída. Talvez mais tarde!
Uso: scriptname foo.html foo.properties outputfoo.html
Quando executado nos arquivos de entrada de amostra do OP, o outputfoo.html contém:
<html>
<head>
<title>foo title</tittle>
</head>
<body> foo body</body>
</html>
... espaço líder para 'foo body' incluído!
MAIS TARDE aconteceu
Eu fiquei curioso o suficiente, e surgiu com uma versão mais bash do acima. Em vez de usar sed, ele usa a expansão de parâmetro do bash em cada substituição, conforme faz um loop no arquivo de entrada.
#!/usr/bin/env bash
# Usage: $0 [input file] [translation file] [output file]
mapfile -t < "$2"
declare -A replacements
for keyvalue in "${MAPFILE[@]}"
do
if [[ $keyvalue =~ (.+)=(.+) ]]
then
k="${BASH_REMATCH[1]}"
v="${BASH_REMATCH[2]}"
replacements[$k]="$v"
fi
done
mapfile -t < "$1"
for line in "${MAPFILE[@]}"
do
for pattern in "${!replacements[@]}"
do
line="${line//\[\[$pattern\]\]/${replacements[$pattern]}}"
done
printf "%s\n" "$line"
done > "$3"