Подтвердить что ты не робот

Как прочитать файл .properties, который содержит ключи с символом периода с помощью Shell script

Я пытаюсь прочитать файл свойств из оболочки script, которая содержит символ периода (.), как показано ниже:

# app.properties
db.uat.user=saple user
db.uat.passwd=secret


#/bin/sh
function pause(){
   read -p "$*"
}

file="./app.properties"

if [ -f "$file" ]
then
    echo "$file found."
 . $file

echo "User Id " $db.uat.user
echo "user password =" $db.uat.passwd
else
    echo "$file not found."
fi

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

Мой файл свойств всегда находится в том же каталоге script или где-то в каталоге/usr/share/doc

4b9b3361

Ответ 1

Поскольку переменные оболочки (Bourne) не могут содержать точки, их можно заменить символами подчеркивания. Прочитайте каждую строку, переведите. в ключе _ и оценить.

#/bin/sh

file="./app.properties"

if [ -f "$file" ]
then
  echo "$file found."

  while IFS='=' read -r key value
  do
    key=$(echo $key | tr '.' '_')
    eval "${key}='${value}'"
  done < "$file"

  echo "User Id       = " ${db_uat_user}
  echo "user password = " ${db_uat_passwd}
else
  echo "$file not found."
fi

Ответ 2

Я использую встроенную функцию grep в bash script для получения свойств из файла .properties.

Этот файл свойств, который я использую в двух местах - для настройки среды разработки и параметров приложения.

Я считаю, что grep может работать медленно в больших циклах, но он решает мои потребности, когда я хочу подготовить среду dev.

Надеюсь, кто-то найдет это полезным.

Пример:

Файл: setup.sh

#!/bin/bash

ENV=${1:-dev}

function prop {
    grep "${1}" env/${ENV}.properties|cut -d'=' -f2
}

docker create \
    --name=myapp-storage \
    -p $(prop 'app.storage.address'):$(prop 'app.storage.port'):9000 \
    -h $(prop 'app.storage.host') \
    -e STORAGE_ACCESS_KEY="$(prop 'app.storage.access-key')" \
    -e STORAGE_SECRET_KEY="$(prop 'app.storage.secret-key')" \
    -e STORAGE_BUCKET="$(prop 'app.storage.bucket')" \
    -v "$(prop 'app.data-path')/storage":/app/storage \
    myapp-storage:latest

docker create \
    --name=myapp-database \
    -p "$(prop 'app.database.address')":"$(prop 'app.database.port')":5432 \
    -h "$(prop 'app.database.host')" \
    -e POSTGRES_USER="$(prop 'app.database.user')" \
    -e POSTGRES_PASSWORD="$(prop 'app.database.pass')" \
    -e POSTGRES_DB="$(prop 'app.database.main')" \
    -e PGDATA="/app/database" \
    -v "$(prop 'app.data-path')/database":/app/database \
    postgres:9.5

Файл: env/dev.properties

app.data-path=/apps/myapp/

#==========================================================
# Server properties
#==========================================================
app.server.address=127.0.0.70
app.server.host=dev.myapp.com
app.server.port=8080

#==========================================================
# Backend properties
#==========================================================
app.backend.address=127.0.0.70
app.backend.host=dev.myapp.com
app.backend.port=8081
app.backend.maximum.threads=5

#==========================================================
# Database properties
#==========================================================
app.database.address=127.0.0.70
app.database.host=database.myapp.com
app.database.port=5432
app.database.user=dev-user-name
app.database.pass=dev-password
app.database.main=dev-database

#==========================================================
# Storage properties
#==========================================================
app.storage.address=127.0.0.70
app.storage.host=storage.myapp.com
app.storage.port=4569
app.storage.endpoint=http://storage.myapp.com:4569
app.storage.access-key=dev-access-key
app.storage.secret-key=dev-secret-key
app.storage.region=us-east-1
app.storage.bucket=dev-bucket

Использование:

./setup.sh dev

Ответ 3

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

#!/bin/bash

# declare an associative array
declare -A arr

# read file line by line and populate the array. Field separator is "="
while IFS='=' read -r k v; do
   arr["$k"]="$v"
done < app.properties

Тестирование:

Используйте declare -p, чтобы показать результат:

  > declare -p arr  

        declare -A arr='([db.uat.passwd]="secret" [db.uat.user]="saple user" )'

Ответ 4

Я нашел использование while IFS='=' read -r немного медленным (я не знаю, почему, может быть, кто-то может кратко объяснить в комментарии или указать на ответ SO?). Я также нашел, что @Nicolai отвечает очень аккуратно как однострочный, но очень неэффективен, так как он будет сканировать весь файл свойств снова и снова для каждого вызова prop.

Я нашел решение, которое отвечает на вопрос, работает хорошо, и это однострочный (бит verbose line).

Решение выполняет поиск, но массирует содержимое перед поиском:

#!/usr/bin/env bash

source <(grep -v '^ *#' ./app.properties | grep '[^ ] *=' | awk '{split($0,a,"="); print gensub(/\./, "_", "g", a[1]) "=" a[2]}')

echo $db_uat_user

Пояснение:

grep -v '^ *#': отменить строки комментариев grep '[^ ] *=': отбрасывает строки без = split($0,a,"="): разделит строку на = и сохраняет в массив a, то есть [1] - ключ, а [2] - значение gensub(/\./, "_", "g", a[1]): заменяет . на _ print gensub... "=" a[2]} объединяет результат gensub выше с = и значением.

Ответ 5

@fork2x

Я пробовал вот так. Пожалуйста, просмотрите и обновите меня, правильно ли это или нет.

#/bin/sh
function pause(){
   read -p "$*"
}

file="./apptest.properties"


if [ -f "$file" ]
then
    echo "$file found."

dbUser=`sed '/^\#/d' $file | grep 'db.uat.user'  | tail -n 1 | cut -d "=" -f2- | sed 's/^[[:space:]]*//;s/[[:space:]]*$//'`
dbPass=`sed '/^\#/d' $file | grep 'db.uat.passwd'  | tail -n 1 | cut -d "=" -f2- | sed 's/^[[:space:]]*//;s/[[:space:]]*$//'`

echo database user = $dbUser
echo database pass = $dbPass

else
    echo "$file not found."
fi