Поиск и замена переменных в файле с использованием bash / sed - PullRequest
5 голосов
/ 29 марта 2012

Я пытаюсь написать скрипт bash (script.sh) для поиска и замены некоторых переменных в файле input.sh. Но мне нужно изменить только те переменные, которые присутствуют в файле variable_list, и оставить остальные как есть.

variable_list

${user}  
${dbname}

input.sh

username=${user}  
password=${password}  
dbname=${dbname}

Ожидаемый выходной файл

username=oracle  
password=${password} > This line won't be changed as this variable(${password}) is not in variable_list file
dbname=oracle

Ниже приведен скрипт, который я пытаюсь использовать, но я не могу найти правильное выражение sed

script.sh

export user=oracle  
export password=oracle123  
export dbname=oracle

variable='variable_list'  
while read line ;  
do  
 if [[ -n $line ]]     
 then  
  sed -i 's/$line/$line/g' input.sh > output.sh  
 fi  
done < "$variable"    

Ответы [ 4 ]

2 голосов
/ 29 марта 2012

Это может сработать:

#!/bin/bash

export user=oracle  
export password=oracle123  
export dbname=oracle

variable='variable_list'  
while read line ;  
do  
 if [[ -n $line ]]
 then
  exp=$(sed -e 's/\$/\\&/g' <<< "$line")
  var=$(sed -e 's/\${\([^}]\+\)}/\1/' <<< "$line")
  sed -i "s/$exp/${!var}/g" input.sh
 fi  
done < "$variable"

Первое выражение sed экранирует символ $, который является метасимволом регулярных выражений. Второй извлекает только имя переменной, затем мы используем косвенное обращение, чтобы получить значение в нашей текущей оболочке и использовать его в выражении sed.

Редактировать

Вместо того, чтобы переписывать файл так много раз, вероятно, более эффективно сделать это следующим образом, составив список аргументов для sed:

#!/bin/bash

export user=oracle  
export password=oracle123  
export dbname=oracle

while read var
do
    exp=$(sed -e 's/\$/\\&/g' <<< "$var")
    var=$(sed -e 's/\${\([^}]\+\)}/\1/' <<< "$var")
    args+=("-e s/$exp/${!var}/g")
done < "variable_list"

sed "${args[@]}" input.sh > output.sh
2 голосов
/ 29 марта 2012

Вот скрипт script.sh, который работает:

#!/bin/bash

user=oracle
password=oracle123
dbname=oracle

variable='variable_list'
text=$(cat input.sh)
while read line
do
  value=$(eval echo $line)  
  text=$(sed "s/$line/$value/g" <<< "$text")
done < "$variable"
echo "$text" > output.sh

Обратите внимание, что ваша оригинальная версия содержит одинарные кавычки вокруг строки sed, которая не вставляет значение $line.Он пытается найти литерал line после конца строки $ (который никогда ничего не найдет).

Поскольку вы ищете значение переменной в $line, вычтобы получить это, нужно выполнить eval.

Кроме того, поскольку существует несколько переменных, над которыми вы зацикливаетесь, промежуточная переменная text сохраняет результат в цикле.

exportКлючевое слово также не нужно в этом сценарии, если только оно не используется в некотором подпроцессе, который не показан.

1 голос
/ 29 марта 2012
user=oracle  
password=oracle123  
dbname=oracle

variable_list=( '${user}' '${dbname}' )

while IFS="=$IFS" read variable value; do
    for subst_var in "${variable_list[@]}"; do
        if [[ $subst_var = $value ]]; then
            eval "value=$subst_var"
            break
        fi
    done
    printf "%s=%s\n" "$variable" "$value"
done < input.sh > output.sh
0 голосов
/ 30 марта 2012

TXR решение. Построить фильтр динамически. Фильтр реализован внутри как трехуровневая структура данных, что дает нам конечный автомат, подобный lex, который сопоставляет весь словарь сразу при сканировании входных данных. Для простоты мы включаем ${ и } как часть имени переменной.

@(bind vars (("${user}" "oracle")
             ("${dbname}" "oracle")
             ("${password}" "letme1n")))
@(next "variable_list")
@(collect)
@entries
@(end)
@(deffilter subst . @(mapcar (op list @1 (second [find vars @1 equal first]))
                             entries))
@(next "input.sh")
@(collect)
@line
@  (output :filter subst)
@line
@  (end)
@(end)

Пробег:

$ txr subst.txr
username=oracle
password=${password}
dbname=oracle

input.sh: (как дано)

username=${user}
password=${password}
dbname=${dbname}

variable_list: (как дано)

${user}
${dbname}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...