Я думаю использовать sed для чтения файла .properties, но задавался вопросом, есть ли более разумный способ сделать это из bash script?
Чтение файла java.properties из bash
Ответ 1
Вышеупомянутые решения будут работать для основ. Однако я не думаю, что они охватывают многострочные значения. Вот awk-программа, которая будет анализировать свойства Java из stdin и производить переменные среды оболочки для stdout:
BEGIN {
FS="=";
print "# BEGIN";
n="";
v="";
c=0; # Not a line continuation.
}
/^\#/ { # The line is a comment. Breaks line continuation.
c=0;
next;
}
/\\$/ && (c==0) && (NF>=2) { # Name value pair with a line continuation...
e=index($0,"=");
n=substr($0,1,e-1);
v=substr($0,e+1,length($0) - e - 1); # Trim off the backslash.
c=1; # Line continuation mode.
next;
}
/^[^\\]+\\$/ && (c==1) { # Line continuation. Accumulate the value.
v= "" v substr($0,1,length($0)-1);
next;
}
((c==1) || (NF>=2)) && !/^[^\\]+\\$/ { # End of line continuation, or a single line name/value pair
if (c==0) { # Single line name/value pair
e=index($0,"=");
n=substr($0,1,e-1);
v=substr($0,e+1,length($0) - e);
} else { # Line continuation mode - last line of the value.
c=0; # Turn off line continuation mode.
v= "" v $0;
}
# Make sure the name is a legal shell variable name
gsub(/[^A-Za-z0-9_]/,"_",n);
# Remove newlines from the value.
gsub(/[\n\r]/,"",v);
print n "=\"" v "\"";
n = "";
v = "";
}
END {
print "# END";
}
Как вы можете видеть, многострочные значения усложняют ситуацию. Чтобы увидеть значения свойств в оболочке, просто источник на выходе:
cat myproperties.properties | awk -f readproperties.awk > temp.sh
source temp.sh
Переменные будут иметь "_" вместо ".", поэтому свойство some.property будет some_property в оболочке.
Если у вас есть файлы свойств ANT, у которых есть интерполяция свойств (например, '$ {foo.bar}'), я рекомендую использовать Groovy с AntBuilder.
Ответ 2
Это, вероятно, самый простой способ: grep + cut
# Usage: get_property FILE KEY
function get_property
{
grep "^$2=" "$1" | cut -d'=' -f2
}
Ответ 3
Я написал script, чтобы решить проблему и поместить ее в свой github.
См. свойства-парсер
Ответ 4
Один из вариантов - написать простую программу Java, чтобы сделать это для вас - затем запустите программу Java в script. Это может показаться глупым, если вы просто читаете свойства из одного файла свойств. Тем не менее, это становится очень полезным, когда вы пытаетесь получить значение конфигурации из чего-то вроде Commons Configuration CompositeConfiguration
, поддерживаемого файлами свойств. Некоторое время мы пошли по пути реализации того, что нам нужно в наших сценариях оболочки, чтобы получить то же поведение, которое мы получали от CompositeConfiguration
. Затем мы разобрались и поняли, что мы должны просто позволить CompositeConfiguration
выполнить эту работу для нас! Я не ожидаю, что это будет популярным ответом, но, надеюсь, вы сочтете это полезным.
Ответ 5
В Perl:
while(<STDIN>) {
($prop,$val)=split(/[=: ]/, $_, 2);
# and do stuff for each prop/val
}
Не тестировалось и должно быть более терпимым к ведущим/конечным пробелам, комментариям и т.д., но вы получите эту идею. Если вы используете Perl (или другой язык) поверх sed
, действительно зависит от того, что вы хотите сделать со свойствами после того, как вы их разобрали из файла.
Обратите внимание, что (как выделено в комментариях) файлы свойств Java могут иметь несколько форм разделителей (хотя я не видел ничего использованного на практике, кроме двоеточий). Следовательно, раскол использует выбор персонажей для разделения.
В конечном итоге вам может быть лучше использовать модуль Config:: Properties в Perl, который создан для решения этой конкретной проблемы.
Ответ 6
Если вы хотите использовать файл sed для parse -any-.properties, вы можете получить довольно сложное решение, поскольку формат позволяет разрывы строк, строки без кавычек, unicode и т.д.: http://en.wikipedia.org/wiki/.properties
Одним из возможных способов обхода решения будет использование самой java для предварительной обработки файла .properties во что-то bash -дружественно, а затем его источник. Например:.
.properties:
line_a : "ABC"
line_b = Line\
With\
Breaks!
line_c = I'm unquoted :(
будет преобразован в:
line_a="ABC"
line_b=`echo -e "Line\nWith\nBreaks!"`
line_c="I'm unquoted :("
Конечно, это приведет к худшей производительности, но реализация будет проще/понятнее.
Ответ 7
У меня есть скрипты оболочки, которые должны искать некоторые .properties и использовать их в качестве аргументов для программ, которые я не писал. Сердцем script является строка, подобная этой:
dbUrlFile=$(grep database.url.file etc/zocalo.conf | sed -e "s/.*: //" -e "s/#.*//")
Эффективно, что grep для ключа и отфильтровать материал перед двоеточием и после любого хэша.
Ответ 8
если вы хотите использовать "оболочку", лучший инструмент для анализа файлов и иметь правильное управление программированием (g) awk. Используйте sed только простую замену.
Ответ 9
Я иногда просто загружал файл свойств в bash script. Это приведет к тому, что переменные среды будут установлены в script с именами и содержимым из файла. Возможно, этого вам и достаточно. Если вам нужно сделать какой-то "настоящий" синтаксический анализ, это, конечно, не путь.
Ответ 10
Хм, я просто столкнулся с той же проблемой сегодня. Это плохое решение человека, по общему признанию, более прямолинейное, чем умное;)
decl=`ruby -ne 'puts chomp.sub(/=(.*)/,%q{="\1";}).gsub(".","_")' my.properties`
eval $decl
тогда свойство 'my.java.prop' можно получить как $my_java_prop.
Это можно сделать с помощью sed или что-то еще, но я, наконец, пошел с ruby для своего "irb", который был удобен для экспериментов. Он довольно ограничен (точки должны быть заменены только до "=", без обработки комментариев), но может быть отправной точкой.
@Daniel, я попытался его загрузить, но Bash не любил точки в именах переменных.
Ответ 11
У меня был некоторый успех с
PROPERTIES_FILE=project.properties
function source_property {
local name=$1
eval "$name=\"$(sed -n '/^'"$name"'=/,/^[A-Z]\+_*[A-Z]*=/p' $PROPERTIES_FILE|sed -e 's/^'"$name"'=//g' -e 's/"/\\"/g'|head -n -1)\""
}
source_property 'SOME_PROPERTY'
Ответ 12
Это решение, которое правильно разбирает кавычки и заканчивается в пространстве, когда не заданы кавычки. Это безопасно: никакой eval
не используется.
Я использую этот код в своих.bashrc и.zshrc для импорта переменных из сценариев оболочки:
# Usage: _getvar VARIABLE_NAME [sourcefile...]
# Echos the value that would be assigned to VARIABLE_NAME
_getvar() {
local VAR="$1"
shift
awk -v Q="'" -v QQ='"' -v VAR="$VAR" '
function loc(text) { return index($0, text) }
function unquote(d) { $0 = substr($0, eq+2) d; print substr($0, 1, loc(d)-1) }
{ sub(/^[ \t]+/, ""); eq = loc("=") }
substr($0, 1, eq-1) != VAR { next } # assignment is not for VAR: skip
loc("=" QQ) == eq { unquote(QQ); exit }
loc("=" Q) == eq { unquote( Q); exit }
{ print substr($1, eq + 1); exit }
' "[email protected]"
}
Это сохраняет имя требуемой переменной и затем переносит массив аргументов, чтобы остальные могли быть переданы как файлы в awk
.
Поскольку так сложно вызвать переменные оболочки и ссылаться на символы кавычек внутри awk
, я определяю их как переменные awk
в командной строке. Q
- символ одной кавычки (апостроф), QQ
- двойная кавычка, а VAR
- это первый аргумент, который мы сохранили ранее.
Для дальнейшего удобства существуют две вспомогательные функции. Первый возвращает местоположение данного текста в текущей строке, а второй печатает содержимое между двумя первыми цитатами в строке с использованием символа кавычки d
(для "разделителя"). Там блуждающий d
с первым substr
в качестве защиты от многострочных строк (см. Ниже "Оговорки").
В то время как я написал код для синтаксиса синтаксиса оболочки POSIX, похоже, отличается от вашего формата только тем, есть ли пробел вокруг привязки. Вы можете добавить эту функциональность к вышеуказанному коду, добавив sub(/[ \t]*=[ \t]*/, "=");
перед sub(…)
на строке awk 4 (обратите внимание: строка 1 пуста).
Четвертая строка удаляет ведущее белое пространство и сохраняет местоположение первого знака равенства. Убедитесь, что ваш awk
поддерживает \t
как вкладку, это не гарантируется в древних системах UNIX.
Строка substr
сравнивает текст перед знаком равенства с VAR
. Если это не соответствует, строка назначает другую переменную, поэтому мы пропустим ее и перейдем к следующей строке.
Теперь мы знаем, что у нас есть заданное назначение переменной, так что это просто вопрос распутывания котировок. Мы делаем это, ища первое местоположение ="
(строка 6) или ='
(строка 7) или без кавычек (строка 8). Каждая из этих строк печатает назначенное значение.
Предостережения. Если есть символ с экранированным кавычком, мы вернем ему значение, усеченное. Обнаружение этого немного нетривиально, и я решил не реализовывать его. Также возникает проблема многострочных кавычек, которые усекаются при разрыве первой строки (это цель "блуждающего d
", упомянутого выше). Большинство решений на этой странице страдают от этих проблем.