Подстановка переменных среды в файле: awk или sed? - PullRequest
1 голос
/ 04 мая 2011

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

# This is a comment
ONE=1
TWO=2
THREE=THREE
# End

В моих сценариях я помещаю этот файл (предположим, что он называется «./vars») в текущую среду и изменяю (некоторые из) переменные на основе пользовательского ввода. Например:

#!/bin/sh
# Read variables
source ./vars
# Change a variable
THREE=3
# Write variables back to the file??
awk 'BEGIN{FS="="}{print $1=$$1}' <./vars >./vars

Как вы можете видеть, я экспериментировал с awk для записи переменных обратно, sed тоже. Безуспешно. Последняя строка скрипта терпит неудачу. Есть ли способ сделать это с помощью awk или sed (желательно с сохранением комментариев, даже комментариев с символом '=')? Или я должен сочетать «чтение» с обрезкой строки в цикле while или какой-то другой магией? Если возможно, я бы хотел избежать использования perl / python и просто использовать инструменты, доступные в Busybox. Большое спасибо.

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

# File: network.config
NETWORK_TYPE=wired
NETWORK_ADDRESS_RESOLUTION=dhcp
NETWORK_ADDRESS=
NETWORK_ADDRESS_MASK=

У меня также есть скрипт с именем 'setup-network.sh':

#!/bin/sh
# File: setup-network.sh

# Read configuration
source network.config

# Setup network
NETWORK_DEVICE=none
if [ "$NETWORK_TYPE" == "wired" ]; then
  NETWORK_DEVICE=eth0
fi
if [ "$NETWORK_TYPE" == "wireless" ]; then
  NETWORK_DEVICE=wlan0
fi
ifconfig -i $NETWORK_DEVICE ...etc

У меня также есть скрипт с именем 'configure-network.sh':

#!/bin/sh
# File: configure-network.sh

# Read configuration
source network.config

echo "Enter the network connection type:"
echo "  1. Wired network"
echo "  2. Wireless network"
read -p "Type:" -n1 TYPE

if [ "$TYPE" == "1" ]; then
  # Update environment variable
  NETWORK_TYPE=wired
elif [ "$TYPE" == "2" ]; then
  # Update environment variable
  NETWORK_TYPE=wireless
fi

# Rewrite configuration file, substituting the updated value
# of NETWORK_TYPE (and any other updated variables already existing
# in the network.config file), so that later invocations of
# 'setup-network.sh' read the updated configuration.
# TODO

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

Ответы [ 3 ]

1 голос
/ 04 мая 2011

Вы не можете использовать awk, читать и писать из одного и того же файла (это часть вашей проблемы).

Я предпочитаю переименовывать файл перед перезаписью (но вы можете сохранить в tmp, а затемтоже переименуйте).

/bin/mv file file.tmp
awk '.... code ...' file.tmp > file

Если ваш env-файл становится больше, вы увидите, что он усекается при размере буфера вашей ОС.

Кроме того, не забывайте, чтоУ gawk (стандартное для большинства установок Linux) есть встроенный массив ENVIRON.Вы можете создать то, что вы хотите из этого

awk 'END {
   for (key in ENVIRON) {
      print key "=" ENVIRON[key]
   }
}' /dev/null

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

Редактировать В частности

   awk -F"=" '{
     if ($1 in ENVIRON) {
         printf("%s=%s\n", $1, ENVIRON[$1])
     }
     # else line not printed or add code to meet your situation
   }' file > file.tmp
   /bin/mv file.tmp file

Редактировать 2 Я думаю, что вашЗначения var = могут иметь значение export, чтобы они были видны массиву awk ENVIRON.

AND

echo PATH=xxx| awk -F= '{print ENVIRON[$1]}'

печатает существующее значение PATH.

Надеюсь, это поможет.

PS, поскольку вы, кажется, являетесь новым пользователем, если вы получите ответ, который поможет вам, пожалуйста, помните, чтобы пометить его как принятый и / или дать ему + (или -) какполезный ответ.

0 голосов
/ 04 мая 2011

Вы можете сделать это просто с помощью bash:

rewrite_config() {
    local filename="$1"
    local tmp=$(mktemp)

    # if you want the header
    echo "# File: $filename" >> "$tmp"

    while IFS='=' read var value; do
        declare -p $var | cut -d ' ' -f 3-
    done < "$filename" >> "$tmp"

    mv "$tmp" "$filename"
}

Используйте это как

source network.config
# manipulate the variables
rewrite_config network.config

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

0 голосов
/ 04 мая 2011

Я точно не знаю, что вы пытаетесь сделать, но если вы пытаетесь изменить значение переменной THREE,

awk -F"=" -vt="$THREE" '$1=="THREE" {$2=t}{print $0>FILENAME}' OFS="=" vars
...