如何读取属性文件包含有使用shell脚本一段字符键

问题描述 投票:36回答:5

我想读一个属性从其中包含一段文字像下面一个shell脚本文件(。):

# 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

我曾尝试在采购文件后,解析该文件,但它不工作,因为键包含了“”性格和存在这样的价值也空格。

我的属性文件始终驻留在脚本的同一目录下或某处在/ usr /共享/ DOC

linux bash shell unix
5个回答
42
投票

作为(伯恩)shell变量不能包含点,你可以用下划线代替它们。阅读每一行,翻译。在关键_和评估。

#/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

需要注意的是,以上只转换。到_,如果你有一个更复杂的格式,您可能需要使用额外的翻译。我最近有解析一个完整的Ant属性,有很多讨厌的字符的文件名,并有我不得不使用:

key=$(echo $key | tr .-/ _ | tr -cd 'A-Za-z0-9_')

60
投票

我用简单的grep内部功能在bash脚本接收来自.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

10
投票

由于在Bash shell变量名不能包含点或空格最好是在这样的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

测试:

使用-p声明显示结果:

  > declare -p arr  

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

1
投票

我发现使用while IFS='=' read -r是有点慢(我不知道为什么,也许有人可以发表评论或指向一个SO回答简单介绍一下?)。我还发现@Nicolai回答的一个班轮很整齐,但效率非常低,因为它会扫描整个性能再次prop的每一次调用文件一遍又一遍。

我发现回答了这个问题,表现良好的解决方案,这是一个班轮(有点冗长线虽然)。

该解决方案做采购,但是按摩的内容采购之前:

#!/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上面=和值。

编辑:正如其他人所指出的,也有一些不兼容问题(AWK),也不会进行验证的内容,看是否在该属性文件的每一行实际上是一个千伏对。但这里的目标是展示一个解决方案,既快速又干净的总体思路。采购似乎是去为它加载的特性,一旦可多次使用的方式。


0
投票

@ 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
© www.soinside.com 2019 - 2024. All rights reserved.