2015-06-10 2 views
1

Я ищу эффективный способ заменить кучу заполнителей/токенов в текстовом файле, предоставленном пользователем, с их соответствующими значениями, хранящимися в простой карте или окружении vars. Дело в том, что файл шаблона будет предоставлен конечным пользователем, поэтому я ищу «безопасный» способ делать только замену переменных без риска выполнения кода и т. Д.Только замена переменных шаблона. Является ли текст/шаблон подходящим?

Стандартный стандарт Go/template "будет работать для самой замены, но накладывает особые требования к форматированию (например, точка". "перед ключом) и открывает другие возможности с помощью своих функций, вызовов, трубопроводов и т. д.

Так что я ищу, в идеале, это функция, которая может анализировать текстовый файл с настраиваемыми разделителями («{{}}» или «$ {}» или «$ ## $») и заменять все обнаруженные маркеры поисками в прилагаемую карту или их env var. Аналогично тому, что делает Python string.Template (https://docs.python.org/2.6/library/string.html?highlight=string.template#string.Template).

Есть ли простой способ настройки или повторного использования библиотеки текста/шаблона для этого? Существуют ли какие-либо другие подходы, которые лучше подходят для использования? Я также изучил варианты не-golang (например, envsubtr, awk и sed скрипты и т. Д.), Поэтому не стесняйтесь идти за пределы Go, если что-то подходит лучше.

вход Пример файла ('template.properties'):

var1=$#VAR_1#$ 
var2=$#VAR_2#$ 

Пример входных данных:

VAR_1 = apples 
VAR_2 = oranges 

Ожидаемый результат после обработки:

var1=apples 
var2=oranges 
+0

Вы можете вручную прочитать файл и выполнить последовательные замены операции для переменных/замены, и вы можете сделать это эффективно, создавая выход на лету. Это можно сделать с довольно небольшим количеством строк кода (~ 30). См. Этот вопрос + ответ, который показывает это в Java: [Альтернатива последовательному String.replace] (http://stackoverflow.com/questions/26735276/alternative-to-successive-string-replace) – icza

+0

Спасибо icza. Реализация моего собственного заменителя определенно является вариантом, но я надеялся найти эффективную и гибкую библиотеку, которая может это сделать. Замена жетонов в строке кажется достаточно общей задачей, которую кто-то еще успел бы решить. – Ike

+0

Что-нибудь вроде [Усы] (https://mustache.github.io/) работает на вас? – n0741337

ответ

1

Это будет работать до тех пор, как ваши имена переменных не содержат ERE метасимволы:

$ cat tst.awk 
NR==FNR { var2val[$1] = $NF; next } 
{ 
    for (var in var2val) { 
     sub("[$]#"var"#[$]",var2val[var]) 
    } 
    print 
} 

$ awk -f tst.awk input.data template.properties 
var1=apples 
var2=oranges 

WRT ваш комментарий ниже о том, отображения в переменных, а не в input.data, это может быть то, что вы ищете для:

$ cat tst.awk 
BEGIN { 
    split(vars,tmp) 
    for (i in tmp) { 
     var2val[tmp[i]] = ENVIRON[tmp[i]] 
    } 
} 
{ 
    for (var in var2val) { 
     sub("[$]#"var"#[$]",var2val[var]) 
    } 
    print 
} 

будет работать с переменными оболочки, как:

$ VAR_1=apples VAR_2=oranges gawk -v vars="VAR_1 VAR_2" -f tst.awk template.properties 
var1=apples 
var2=oranges 

или:

$ export VAR_1=apples 
$ export VAR_2=oranges 
$ gawk -v vars="VAR_1 VAR_2" -f tst.awk template.properties 
var1=apples 
var2=oranges 

или:

$ VAR_1=apples 
$ VAR_2=oranges 
$ VAR_1="$VAR_1" VAR_2="$VAR_2" gawk -v vars="VAR_1 VAR_2" -f tst.awk template.properties 
var1=apples 
var2=oranges 

Обратите внимание, что это поглазеть конкретных вследствие ENVIRON и требует VAR_1 и т.д., которые будут экспортированы или установить в командной строке, как она у меня выше.

Или, может быть, это то, что вы хотите:

$ cat tst.awk 
BEGIN { 
    var2val["VAR_1"] = VAR_1 
    var2val["VAR_2"] = VAR_2 
} 
{ 
    for (var in var2val) { 
     sub("[$]#"var"#[$]",var2val[var]) 
    } 
    print 
} 

$ VAR_1=apples 
$ VAR_2=oranges 
$ awk -v VAR_1="$VAR_1" -v VAR_2="$VAR_2" -f tst.awk template.properties 
var1=apples 
var2=oranges 
+1

Спасибо за фрагмент @EdMorton. В настоящее время у меня есть исходный var/values ​​в структуре данных (в программе Go или Python) или переменных среды. Я могу написать данные var в файл temp, чтобы это работало, как было предложено. Существует ли тривиальный способ «передать» данные или просмотреть awk-скрипт из экспортированных переменных оболочки оболочки, которые не требуют создания временного файла с ним? – Ike

+0

Извините, я никогда не слышал о «Go» и не мог сказать программу Python из отверстия в земле. Когда вы говорите «env vars» - вы говорите о переменных оболочки или о чем-то еще? Что бы это ни было, отредактируйте свой вопрос, чтобы показать его. –

+0

@Ike Я отредактировал мой вопрос, чтобы показать несколько возможных решений одной возможной интерпретации вашего комментария о наличии значений в env vars. –

0

Просто используйте FastTemplate [1]. Он отлично соответствует вашим требованиям:

  • Можно использовать разделители начала и конца произвольных заполнителей.
  • Нулевой риск для ненадежного ввода, потому что нет никакой логики, кроме замены замещающих.
  • Работает намного быстрее, чем текст/шаблон (на 10x).

[1] https://github.com/valyala/fasttemplate

Смежные вопросы