Заполнение заполнителей в файле за один проход

StackOverflow https://stackoverflow.com/questions/407279

Вопрос

У меня есть текстовый файл скелета со строками-заполнителями:

blah blah blah
blah $PLACEHOLDER_1$
blah
$PLACEHOLDER_2$

и так далее.Конкретная «форма» заполнителей не имеет значения — я могу изменить их на любые, наиболее удобные для конкретной реализации.

У меня есть сценарий bash, в котором я знаю значения заполнителей, и мне нужно создать новый файл, в котором заполнители будут заменены значениями.

#! /bin/sh
PLACEHOLDER_1 = 'string 1'
PLACEHOLDER_2 = 'multiline 
string 
2'
# TODO: Generate file output.txt from file output.template 
#       using placeholders above.

Я могу сделать это за несколько проходов с помощью sed, но это неинтересно.Я делаю нет хочу использовать Perl.Я хочу использовать только textutils и bash.

Как лучше всего сделать то, что я хочу, за один проход?

Это было полезно?

Решение

Вы по-прежнему можете использовать sed для замены за один проход.Вам просто нужно указать все замены в одной команде.

например.

sed -i 's/PLACEHOLDER_1/string 1/g;s/PLACEHOLDER_2/string 2/g' <file>

Другие советы

Вот способ сделать это без sed:

Во-первых, слегка измененный файл шаблона, в котором заполнителями являются переменные bash:

blah blah blah
blah $PLACEHOLDER_1
blah
$PLACEHOLDER_2

И сценарий:

#! /bin/sh
templatefile=output.template
outputfile=output.txt

PLACEHOLDER_1='string 1'

PLACEHOLDER_2='multiline 
string 
2'

# DONE: Generate file output.txt from file output.template 
#       using placeholders above.

echo "$(eval "echo \"$(cat $templatefile)\"")" > $outputfile

Вот версия, демонстрирующая шаблон, содержащийся в скрипте, но с некоторыми изменениями.Он также демонстрирует значения по умолчанию, которые также можно использовать в версии файла шаблона, а также в шаблоне можно выполнять математические операции:

#! /bin/sh
template='blah blah blah
blah $PLACEHOLDER_1
blah
${PLACEHOLDER_2:-"some text"} blah ${PLACEHOLDER_3:-"some
lines
of
text"} and the total is: $((${VAL_1:-0} + ${VAL_2:-0}))'
# default operands to zero (or 1) to prevent errors due to unset variables
outputfile=output.txt

# gears spin, bells ding, values for placeholders are computed

PLACEHOLDER_1='string 1'

PLACEHOLDER_2='multiline 
string 
2'

VAL_1=2

VAL_2=4

unset PLACEHOLDER_3 # so we can trigger one of the defaults

# Generate file output.txt from variable $template 
#       using placeholders above.

echo "$(eval "echo \"$template\"")" > $outputfile

Никаких sed, никаких циклов, только запутанное вложение и кавычки.Я почти уверен, что цитирование защитит вас от вредоносного содержимого в файле шаблона, но я не собираюсь этого гарантировать.

Основываясь на предыдущем ответе, возможно, использовать массив и вычислить строку sed?

#!/bin/sh
PLACEHOLDER[0]='string 1'
PLACEHOLDER[1]='multiline 
string 
2'

s="sed -i "
for(( i=0 ; i<${#PLACEHOLDER[*]} ; i++ )) ; do 
    echo ${PLACEHOLDER[$i]}
    s=$s"s/PLACEHOLDER_$i/${PLACEHOLDER[$i]}/g;"
done
echo $s

Однако, похоже, не работает с многострочными строками.

Я не знаю, насколько портативными могут быть массивы Bash.Приведенный выше фрагмент протестирован с использованием «GNU bash, версия 3.2.17(1)-релиз (i386-apple-darwin9.0)»

Мое единственное решение bash:

TEMPLATE='
foo
$var1
bar
$var2'
eval "echo \"$TEMPLATE\""

Я просто наткнулся на этот вопрос, потому что искал то же самое, и нашел envsubst(1).

Вы можете использовать envsubst если вы не против использовать переменные среды:

PLACEHOLDER_1='string 1' PLACEHOLDER_2='multiline 
string 
2' envsubst < output.template 

Если у вас много переменных, вы можете сохранить их в файле и просто source это (не забудьте использовать export в конце исходного файла!)

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top