
У меня есть переменная, которая имеет такое значение
line=dog,/path1,/path2
Я хочу создать переменную из значения; т.е. это dog
должна быть переменная, и хочу получить следующий вывод:
dog=/path1,/path2
dog1=/path1
dog2=/path2
Аналогично, если у меня есть, line=bull,/val1,/val2
мне нужен следующий вывод
bull=/val1,/val2
bull1=/val1
bull2=/val2
Обратите внимание, что line
будет только три значения, разделенные запятыми.
решение1
Я думаю, это именно то, что вы пытаетесь сделать:
line='dog,/path1,/path2'
IFS=', ' read -r -a dog <<< "$line"
echo "$dog"
dog
echo "${dog[1]}"
/path1
echo "${dog[2]}"
/path2
Предполагается, что ваша оболочка — bash.
решение2
Вот решение, ориентированное на 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
знаком равенства, затем третье значение, 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 в файл.
решение3
Если вы используете 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
ВОЛЯтерпеть неудачу, если какое-либо из значений поля содержит пробелы и т. д. например line=dog,/path /with / spaces,/path2
. Вы можете исправить это, если требуется, выведя соответствующие кавычки из операторов print
и printf
в perl
скрипте. И/или определив $newline
как массив bash вместо строки. Оставлено в качестве упражнения для читателя, поскольку я уже достаточно показал принцип/метод, используемый здесь.
Если вы хотите объявить их как экспортируемые переменные, используйте:
declare -x $newline
help declare
для более подробной информации см .
Кстати, в ksh
можно использовать typeset
вместо declare
. typeset
также поддерживается, bash
но считается устаревшим (см. help typeset
в bash
).
Наконец: вы уверены, что не предпочли бы использовать переменную-массив оболочки (например dog[0]=/path1,/path2
, dog[1]=/path1
, и dog[2]=/path2
) вместо отдельных переменных? Именно для таких вещей они и существуют.
решение4
Вы можете сделать что-то вроде этого. Я определяю строку так же, как у вас. Затем я анализирую наш первый токен, разделенный запятыми, из строки (я предполагаю, что это будет допустимо для имени переменной). Затем я создаю две новые переменные на основе первого токена и назначаю их второму и третьему токенам, разделенным запятыми, из строки.
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