Создайте текст, соответствующий множественным присвоениям переменных из одной переменной

Вы можете установить ограничения перед запуском процесса. Например, установите ограничение виртуальной (мягкой) памяти для текущей оболочки на 1 ГБ

ulimit -S 1048576

. Вы также можете установить такие ограничения для всей системы, например, у меня есть это:

  • /etc/security/limits.conf:

     * soft as 25165824 
     * hard as 25165824 
     
  • /etc/systemd/system.conf:

     DefaultLimitAS = 25769803776 
     

Чтобы ограничить все процессы 24G на мои системы 32G. Хотя два процесса вместе могли вызвать такую ​​ситуацию OOM, на практике этого никогда не происходило.

Относительно «долгое время не отвечал, прежде чем убить наступательный процесс»:

  • Не используйте раздел подкачки, тогда все будет убито быстро.

Обратите внимание: на самом деле проблема не в malloc (виртуальной памяти). OOM происходит только тогда, когда процесс начинает использовать эту распределенную память. К сожалению, в Linux вы не можете ограничить резидентную память. См. «Перегрузка памяти»:

2
20.05.2016, 18:38
4 ответа

Если вы используете bash, вы можете сделать что-то вроде этого (с дополнительными echo операторами, чтобы показать, что происходит на каждом этапе):

$ line=dog,/path1,/path2

$ newline=$(printf "%s\n" "$line" | 
            perl -n -e 'BEGIN {$count=1};
                        my ($var,@values) = split /,/;
                        print "$var=" . join(",",@values);
                        foreach (@values) {
                            printf "%s%i=\"%s\" ",$var, $count++, $_
                        }')

$ echo "$newline"
dog=/path1,/path2 dog1=/path1 dog2=/path2

$ declare $newline

$ declare | grep '^dog'
dog=/path1,/path2
dog1=/path1
dog2=/path2

Это использует perl для разделения $line запятыми. Первое поле сохраняется в $var, остальные - в массиве @values. Затем он производит вывод, пригодный для использования с командой bash declare для установки переменных.

Обратите внимание, что $newline в строке declare не заключается и не должен заключаться в двойные кавычки. Если она будет заключена в двойные кавычки, declare получит только один аргумент, а не три, разделенные пробелами.

Одним из неприятных побочных эффектов отсутствия кавычек здесь является то, что declare WILL не работает, если любое из значений поля содержит пробелы и т.д. Например, line=dog,/path /with / spaces,/path2. При необходимости это можно исправить, выводя соответствующие цитаты из операторов print и printf в скрипте perl. И/или определив $newline как массив bash вместо строки. Оставим это упражнение для читателя, так как я уже достаточно показал принцип/технику, используемую здесь.

Если вы хотите объявить их как экспортируемые переменные, используйте:

declare -x $newline

подробнее см. в help declare.

BTW, в ksh вы можете использовать typeset вместо declare. typeset также поддерживается bash, но считается устаревшим (см. help typeset в bash).


И наконец: вы уверены, что не предпочли бы использовать переменную массива shell (например, dog[0]=/path1,/path2, dog[1]=/path1, и dog[2]=/path2), а не отдельные переменные? Именно для таких вещей они и существуют.

1
27.01.2020, 21:56

Вы можете сделать что-то вроде этого. Я определяю линию как у вас. Затем я анализирую наш первый токен, разделенный запятыми, из строки (я предполагаю, что здесь он будет действителен для имени переменной). Затем я создаю две новые переменные на основе первого токена и назначаю их второму и третьему разделенным запятыми токенам из строки.

line="dog,/path1,/path2"
first="$(echo "${line}" | awk -F, '{ print $1 }')"
eval "${first}1=$(echo "${line}" | awk -F, '{ print $2 }')"
eval "${first}2=$(echo "${line}" | awk -F, '{ print $3 }')"

echo "${dog1}"
/path1
echo "${dog2}"
/path2
0
27.01.2020, 21:56

Вот решение, ориентированное на bash:

IFS=, read -r -a vars <<<"$line"
printf "%s\n" "${vars[0]}=${vars[1]},${vars[2]}" "${vars[0]}1=${vars[1]}" "${vars[0]}2=${vars[2]}"

Первая строка разделяет вашу переменную $ line на части на основе запятых. Вторая строка, работающая наизнанку:

  1. выводит первое значение (например, «собака»), знак равенства, затем вторые два значения,
  2. выводит первое значение с суффиксом 1 , знак равенства, затем второе значение,
  3. выводит первое значение с суффиксом 2 , знак равенства, затем третье значение,
  4. printf эти три строки, разделенные переводом строки.

Этот ответ, как и ваш вопрос, жестко запрограммирован на наличие трех значений в $ line .

Пример ввода и вывода (первые $ - это приглашения оболочки):

$ line=dog,/path1,/path2
$ IFS=, read -r -a vars <<<"$line"
$ printf "%s\n" "${vars[0]}=${vars[1]},${vars[2]}" "${vars[0]}1=${vars[1]}" "${vars[0]}2=${vars[2]}"
dog=/path1,/path2
dog1=/path1
dog2=/path2

Вы можете достаточно легко перенаправить вывод printf в файл.

2
27.01.2020, 21:56

Я думаю, что это то, что вы пытаетесь сделать:

line='dog,/path1,/path2'
IFS=', ' read -r -a dog <<< "$line"

echo "$dog"
dog
echo "${dog[1]}"
/path1
echo "${dog[2]}"
/path2 

Предполагается, что ваша оболочка - bash.

2
27.01.2020, 21:56

Теги

Похожие вопросы