localize e substitua os valores de colchetes duplos

2

Eu tenho um requisito para substituir o [[KEY]] entre colchetes duplos em um dos arquivos html com VALUE . Valores-chave estão disponíveis em arquivos diferentes. Após a substituição, eu preciso colocar saída em arquivo separado.

Assim, temos dois arquivos de entrada e um de saída como argumento.

arquivo html: foo.html

<html>
<head>
<title>[[title]]</tittle>
</head>
<body>[[body]]</body>
</html>

arquivo de propriedades: foo.properties

title=foo title
body= foo body

arquivo de saída

<html>
<head>
<title>foo title</tittle>
</head>
<body>foo body</body>
</html>

Como posso criar meu script bash passando todos os nomes de arquivo nos argumentos?

    
por killer 08.04.2016 / 15:25

2 respostas

2

com sed :

sed -f <(sed 's/\(.*\)=\(.*\)/s\/\[\[\]\]\/\//' foo.properties) foo.html

A invocação interna de sed constrói os pares search e replace, que depois são lidos pelo sed externo via -f (script-file).

Ele cria os comandos sed do arquivo foo.properties da seguinte forma:

s/\[\[name\]\]/replace string/

São lidos e executados no segundo arquivo foo.html .

    
por 08.04.2016 / 15:43
1

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:

  1. mapfile para ler o arquivo de entrada (na matriz MAPFILE padrão), cortando as novas linhas ( -t )

  2. 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.

  3. 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"
    
por 08.04.2016 / 19:16