Оболочка синтаксического анализа - PullRequest
3 голосов
/ 03 февраля 2012

Я читаю строку из файла с переменными сценария оболочки и хочу заменить переменные значениями в такой функции, как

hello.txt:
-------------
Hello $NAME


a.sh 
-------------
function printout
{
  echo ???somehow_parse??? $1
}

NAME=Joe
printout "$(cat hello.txt)"
NAME=Nelly
printout "$(cat hello.txt)"

Пример не самый лучший, но он описывает мою проблему.Другими словами: могу ли я использовать shell в качестве движка шаблонов?

Я использую ksh.

Ответы [ 4 ]

1 голос
/ 03 февраля 2012

Если вы уверены, что содержимое вашего файла шаблона полностью безопасно, то есть в нем нет строки для выполнения команды, которая может нанести вред вашему компьютеру, тогда вы можете использовать eval :

#!/bin/bash
NAME=Joe
TEMPLATE=$(cat hello.txt)
eval "echo $TEMPLATE"
NAME=Nelly
eval "echo $TEMPLATE"

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

HELLO Joe
HELLO Nelly
1 голос
/ 03 февраля 2012

В общем, я бы выбрал подход поиска и замены с использованием sed / awk, такой как показан в ответ Кента или этот ответ .

Если вы хотите использовать только оболочку, тогда стандартным способом будет использование eval. Однако это создает угрозу безопасности. Например:

[me@home]$ cat hello.txt
hello $NAME; uname -a
[me@home]$ NAME="shawn"
[me@home]$ eval echo "`cat hello.txt`"   # DO NOT DO THIS!
hello shawn
Linux SOMEHOST 2.6.9-101.ELsmp #1 SMP Fri May 27 18:57:30 EDT 2011 i686 i686 i386 GNU/Linux

Обратите внимание, как команда может быть введена в шаблон!

Однако вы можете уменьшить риск, используя этот подход:

[me@home]$ eval "OUT=\"`cat hello.txt`\""
[me@home]$ echo $OUT
hello shawn; uname -a

Обратите внимание, что это все еще не надежно , поскольку команды все еще могут вводиться с использованием $(cmd) или `cmd`.

Короче говоря, вы должны использовать eval, только если вы понимаете риски и можете контролировать / ограничивать доступ к файлам шаблонов.

Вот пример того, как это можно применить в вашем скрипте:

function printout {
    FILENAME=$1
    eval "OUT=\"`cat $FILENAME`\""
    echo $OUT
}

NAME=Joe
printout hello.txt
NAME=Nelly
printout hello.txt
0 голосов
/ 11 апреля 2012

Я думаю, что самое простое решение - использовать утилиту * 1001. ** и получите вывод, который выглядит следующим образом:

/home/you/stuff
myfile.txt
myfile
0 голосов
/ 03 февраля 2012

как это?

kent$  head hello.txt t.sh
==> hello.txt <==
hello $name

==> t.sh <==
#!/bin/bash

function printout
{
  echo $1|awk -v name="$name" 'gsub(/\$name/,name)'
}
name=xxx
printout "$(cat hello.txt)"
name=yyy
printout "$(cat hello.txt)"

запустите:

kent$  ./t.sh
hello xxx
hello yyy
...