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

Чтение файла java.properties из bash

Я думаю использовать sed для чтения файла .properties, но задавался вопросом, есть ли более разумный способ сделать это из bash script?

4b9b3361

Ответ 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 ", упомянутого выше). Большинство решений на этой странице страдают от этих проблем.