Переменные, перечисленные в переменной, повторяются вместо обработанных [duplicate]

У меня есть часть скрипта, как показано ниже.

notify() { printf -v "old_notif" "%d" "$notif_$2" now=$(date +%s) fark=$((now - old_notif)) echo $old_notif if [ -z $old_notif ]; then

.....

x1=$(date +%s) export "notif_$2=$x1"

Я вызываю уведомление с двумя параметрами.

notify xyz klm

Я создаю динамическую переменную в функции с экспортом. И главный скрипт находится в цикле while. Мой вопрос: как я могу использовать переменную notif_$2 в проверке if? Или как я могу назначить его десятичное содержимое другой переменной? В примере, который я попытался с помощью printf, он не назначает контент.

2
задан 29 June 2017 в 05:09

2 ответа

ТЛ;др: один путь-это [клавиши f21].

Вы пытаетесь расширить параметра (в данном случае, переменная), чье имя само должно быть получено за счет расширения другого параметра (в данном случае, позиционным параметром). Кроме того, позиционный параметр должен быть расширен, затем сцепляются с текстом notif_, чтобы произвести текст, который затем сам должен быть расширен.

Баш позволяет сделать это аккуратно с ТЛ;др: или nameref.

в первых двух разделах этого поста показать падени-в замене для вашей команды printf -v, используя эти методы. Остальные разделы являются обязательными; они далее объясняют эти особенности и то, что вы можете сделать с ними.

способ 1: косвенные расширения

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

local tmp="notif_$2" printf -v "old_notif" "%d" "${!tmp}"

[f25 привод датчика] делает tmp параметр локальный для функции оболочки. Если по каким-то причинам Вы не хотите, что просто опустить слово local. Параметр не должен быть вызван tmp.

косвенные расширение транслируется в 3.5.3 расширение параметр Shell в Баш справочное руководство.

способ 2: Namerefs

[dиода d17]другой способ заключается в использовании 3.5.3 расширение параметр оболочки в nameref относится к параметру. Вы создаете его из имени параметра, но однажды созданный, он ведет себя так, как будто это тот параметр, когда вы читаете или пишите.[!dиода d17]

, чтобы использовать nameref, заменить вашу команду printf -v с:

local -n ref="notif_$2" printf -v "old_notif" "%d" "$ref"

передав параметр [f30 с], чтобы local или [f32 из] причин вновь введенных параметров nameref. Обратите внимание, что в команде printf, вы будете использовать обычный разложения по параметру ($ref) -- не косвенные экспансия -- потому что оболочка выполняет косвенный автоматически для nameref.

Вы не можете пропустить local здесь, хоть в (необычные) случай, когда вы хотели nameref, чтобы быть полезной после того, как функция вернула, можно заменить его [f36 в].

(в зависимости от ваших потребностей, это может быть даже имеет смысл использовать nameref не только эти две линии. Чтобы узнать как, читайте дальше.)

Namerefs покрыты 3.4 параметры оболочки в Баш справочное руководство.

подробное объяснение: как косвенные работы по расширению

оболочка имеет наиболее легко продемонстрирована с помощью интерактивного использования, но позиционные параметры (например, [fунции f37], расширена с помощью $2) не совсем одинаковый смысл вне оболочки функции, и [f39 расстройства] встроенный не работает вообще вне функция (можно использовать declare вместо этого, или ничего).

так, для начала упрощенный пример, предположим, что вы работаете в интерактивном режиме в командной строке и запуска:

x=foo export "notif_$x=1234"

после запуска, что 1234 хранится в параметре notif_foo. (Он также экспортирует этот параметр как переменную среды.) Мы можем увидеть это путем проверки notif_foo:

echo "$notif_foo"

выводит [пулемет f44].

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

но вы можете создать именем параметр и поместить его в другой параметр:

y="notif_$x"

теперь y держит notif_foo, так что вы можете использовать косвенные расширение на y, который выглядит так:

"${!y}"

, что расширяет 1234, как если бы Вы использовали "$notif_foo". Но вам не нужно знать $x это foo, чтобы использовать его.[!dапример д35]

, это назначение 1234 для old_notif:

old_notif="${!y}"

если вам нужно отформатировать содержимое [f55, которая], вы можете сделать это, тоже. Например, вы можете использовать printf если вам это нужно. Эта команда аналогична команде в вашем вопросе printf, и имеет эффект назначение 1234 для old_notif:

printf -v old_notif '%d' "${!y}"

(он также работает в своем оригинальном стиле цитирования, т. е. [от f60] имеет тот же эффект.)

конечно, это полагается на y параметр соответствующим образом назначены в первую очередь.

[и D40]написать свою оболочку функции, вы замените $x с $2, и вы будете, вероятно, хотеть использовать [64-го фокуса] встроенный, чтобы предотвратить вашу временную переменную, что я буду теперь звать [f65 в] вместо y--вытекла из функции области.[!и D40] local tmp="notif_$2" printf -v old_notif '%d' "${!tmp}" [dрайвер d41]или, используя стиль цитирования, который Вы использовали в вопросе:[!dрайвер d41] local tmp="notif_$2" printf -v "old_notif" "%d" "${!tmp}"

подробное объяснение: как работать Namerefs

[d43 см.], чтобы попробовать namrefs в интерактивном режиме, вы должны использовать declare -n, а не [f68 не] (поскольку local работает только ... или нужно-внутри тела функции оболочки).[!d43 см.]

как и прежде, предположим, вы запустили:

x=foo export "notif_$x=1234"

таким образом [р70] расширяет 1234. Вы можете создать nameref для именованного параметра в результате расширения "notif_$x":

declare -n y="notif_$x"

теперь y название notif_foo, и обычный параметр расширения [f75 в Джей] автоматически разыменовать это имя, тем самым расширяя notif_foo параметр. То есть, это расширяет [f77 на английском языке], как если бы Вы использовали $notif_foo:

[от f13]

написать функцию оболочки, вы замените $x с $2, и я рекомендую использовать local вместо declare. Я предлагаю также использовать более описательное имя, чем y; за короткий функция без другие объявления nameref, [f84-это, наверное, достаточно понятны.

local -n ref="notif_$2" print -v old_notif '%d' "$ref"

или, с стиль цитирование вы используете:

local -n ref="notif_$2" print -v "old_notif" "%d" "$ref"

Namerefs мощные

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

x=foo declare -n y="notif_$x" y=1234

вторая команда создает nameref к параметру, который может еще не существовать. Это не проблема! Он будет создан при первом назначении его, даже если назначение что в nameref.

третья команда выглядит он назначает 1234 для y, но на самом деле он присваивает его notif_foo. Теперь оба [f88 и f89] расширить 1234. [f91 со шляпками] расширяет 1234, потому что это значение, хранящееся в notif_foo; $y расширяет 1234, потому что y это nameref для notif_foo.

предположим, что вы [о d54]смотрит!о d54] знать, что y относится, хотя. То есть, предположим, что вы хотите сделать notif_foo, а не [выключателей f100], от y. Ну, вы можете, потому что с nameref, косвенные расширения имеет противоположность своего обычного эффекта. Это расширяет notif_foo:

[f17 в] [размером d57]в вашей функции, вы могли бы ввести notif_$2 через nameref.[!размером d57]

отсюда напрашивается еще один способ борьбы с notif_$2 в функции: вы можете ввести его через nameref и использовать nameref для каждого последующего доступа.

в настоящее время у вас есть:

x1=$(date +%s) export "notif_$2=$x1"

в качестве альтернативы, вы могли бы использовать:

[зг19]

это самое трудное, что надо, хотя, так, вероятно, вы создали только [dадувных подушек безопасности f105] параметр, потому что export "notif_$2=$(date +%s)" трудно читать. ref="$(date +%s)" это хоть и просто,, так что вы можете пропустить строку x1= и пишите:

local -n ref="notif_$2" ref="$(date +%s)" export "${!ref}=$ref"

мне кажется, что вы могли бы использовать [то f109] просто присвоить параметр для использования в командной строке. Если вы на самом деле не нужно экспортировать его в дочерние процессы, то вы можете просто использовать первые две строки, и это проще, чем у вас.

[d63, как если вам нужно экспортировать его, используйте все три. Это все-таки немного сложнее, чем то, что вы... но она может позволить вам упростить остальные функции, потому что, после этого:[!d63, как] вместо того, чтобы писать notif_$2, вы можете просто написать [из нержавеющей стали f111 имеет]. Это работает даже в тех случаях, когда писать notif_$2 неадекватов. То есть, это уже не нужно делать ничего особенного (как способ 1 и способ 2 выше), чтобы расширить параметр, имя которого является результатом расширения notif_$2. Просто напишите ref. Это работает даже для написания-и создание, и отключения -- параметр. (После точки объявления, [115 этаж] пишет и даже может создать ссылается на параметр; unset ref сбрасывает ссылается на параметр.) [г70]если вы собираетесь использовать nameref на протяжении всей вашей функции, вы, возможно, захотите придумать более значимое имя, чем ref. (Лучшее название, конечно, быть определено задание, вы пишете функцию для выполнения.)[!г70]
2
ответ дан 18 July 2018 в 06:51

ТЛ;др: один путь-это [клавиши f21].

Вы пытаетесь расширить параметра (в данном случае, переменная), чье имя само должно быть получено за счет расширения другого параметра (в данном случае, позиционным параметром). Кроме того, позиционный параметр должен быть расширен, затем сцепляются с текстом notif_, чтобы произвести текст, который затем сам должен быть расширен.

Баш позволяет сделать это аккуратно с ТЛ;др: или nameref.

в первых двух разделах этого поста показать падени-в замене для вашей команды printf -v, используя эти методы. Остальные разделы являются обязательными; они далее объясняют эти особенности и то, что вы можете сделать с ними.

способ 1: косвенные расширения

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

local tmp="notif_$2" printf -v "old_notif" "%d" "${!tmp}"

[f25 привод датчика] делает tmp параметр локальный для функции оболочки. Если по каким-то причинам Вы не хотите, что просто опустить слово local. Параметр не должен быть вызван tmp.

косвенные расширение транслируется в 3.5.3 расширение параметр Shell в Баш справочное руководство.

способ 2: Namerefs

[dиода d17]другой способ заключается в использовании 3.5.3 расширение параметр оболочки в nameref относится к параметру. Вы создаете его из имени параметра, но однажды созданный, он ведет себя так, как будто это тот параметр, когда вы читаете или пишите.[!dиода d17]

, чтобы использовать nameref, заменить вашу команду printf -v с:

local -n ref="notif_$2" printf -v "old_notif" "%d" "$ref"

передав параметр [f30 с], чтобы local или [f32 из] причин вновь введенных параметров nameref. Обратите внимание, что в команде printf, вы будете использовать обычный разложения по параметру ($ref) -- не косвенные экспансия -- потому что оболочка выполняет косвенный автоматически для nameref.

Вы не можете пропустить local здесь, хоть в (необычные) случай, когда вы хотели nameref, чтобы быть полезной после того, как функция вернула, можно заменить его [f36 в].

(в зависимости от ваших потребностей, это может быть даже имеет смысл использовать nameref не только эти две линии. Чтобы узнать как, читайте дальше.)

Namerefs покрыты 3.4 параметры оболочки в Баш справочное руководство.

подробное объяснение: как косвенные работы по расширению

оболочка имеет наиболее легко продемонстрирована с помощью интерактивного использования, но позиционные параметры (например, [fунции f37], расширена с помощью $2) не совсем одинаковый смысл вне оболочки функции, и [f39 расстройства] встроенный не работает вообще вне функция (можно использовать declare вместо этого, или ничего).

так, для начала упрощенный пример, предположим, что вы работаете в интерактивном режиме в командной строке и запуска:

x=foo export "notif_$x=1234"

после запуска, что 1234 хранится в параметре notif_foo. (Он также экспортирует этот параметр как переменную среды.) Мы можем увидеть это путем проверки notif_foo:

echo "$notif_foo"

выводит [пулемет f44].

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

но вы можете создать именем параметр и поместить его в другой параметр:

y="notif_$x"

теперь y держит notif_foo, так что вы можете использовать косвенные расширение на y, который выглядит так:

"${!y}"

, что расширяет 1234, как если бы Вы использовали "$notif_foo". Но вам не нужно знать $x это foo, чтобы использовать его.[!dапример д35]

, это назначение 1234 для old_notif:

old_notif="${!y}"

если вам нужно отформатировать содержимое [f55, которая], вы можете сделать это, тоже. Например, вы можете использовать printf если вам это нужно. Эта команда аналогична команде в вашем вопросе printf, и имеет эффект назначение 1234 для old_notif:

printf -v old_notif '%d' "${!y}"

(он также работает в своем оригинальном стиле цитирования, т. е. [от f60] имеет тот же эффект.)

конечно, это полагается на y параметр соответствующим образом назначены в первую очередь.

[и D40]написать свою оболочку функции, вы замените $x с $2, и вы будете, вероятно, хотеть использовать [64-го фокуса] встроенный, чтобы предотвратить вашу временную переменную, что я буду теперь звать [f65 в] вместо y--вытекла из функции области.[!и D40] local tmp="notif_$2" printf -v old_notif '%d' "${!tmp}" [dрайвер d41]или, используя стиль цитирования, который Вы использовали в вопросе:[!dрайвер d41] local tmp="notif_$2" printf -v "old_notif" "%d" "${!tmp}"

подробное объяснение: как работать Namerefs

[d43 см.], чтобы попробовать namrefs в интерактивном режиме, вы должны использовать declare -n, а не [f68 не] (поскольку local работает только ... или нужно-внутри тела функции оболочки).[!d43 см.]

как и прежде, предположим, вы запустили:

x=foo export "notif_$x=1234"

таким образом [р70] расширяет 1234. Вы можете создать nameref для именованного параметра в результате расширения "notif_$x":

declare -n y="notif_$x"

теперь y название notif_foo, и обычный параметр расширения [f75 в Джей] автоматически разыменовать это имя, тем самым расширяя notif_foo параметр. То есть, это расширяет [f77 на английском языке], как если бы Вы использовали $notif_foo:

[от f13]

написать функцию оболочки, вы замените $x с $2, и я рекомендую использовать local вместо declare. Я предлагаю также использовать более описательное имя, чем y; за короткий функция без другие объявления nameref, [f84-это, наверное, достаточно понятны.

local -n ref="notif_$2" print -v old_notif '%d' "$ref"

или, с стиль цитирование вы используете:

local -n ref="notif_$2" print -v "old_notif" "%d" "$ref"

Namerefs мощные

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

x=foo declare -n y="notif_$x" y=1234

вторая команда создает nameref к параметру, который может еще не существовать. Это не проблема! Он будет создан при первом назначении его, даже если назначение что в nameref.

третья команда выглядит он назначает 1234 для y, но на самом деле он присваивает его notif_foo. Теперь оба [f88 и f89] расширить 1234. [f91 со шляпками] расширяет 1234, потому что это значение, хранящееся в notif_foo; $y расширяет 1234, потому что y это nameref для notif_foo.

предположим, что вы [о d54]смотрит!о d54] знать, что y относится, хотя. То есть, предположим, что вы хотите сделать notif_foo, а не [выключателей f100], от y. Ну, вы можете, потому что с nameref, косвенные расширения имеет противоположность своего обычного эффекта. Это расширяет notif_foo:

[f17 в] [размером d57]в вашей функции, вы могли бы ввести notif_$2 через nameref.[!размером d57]

отсюда напрашивается еще один способ борьбы с notif_$2 в функции: вы можете ввести его через nameref и использовать nameref для каждого последующего доступа.

в настоящее время у вас есть:

x1=$(date +%s) export "notif_$2=$x1"

в качестве альтернативы, вы могли бы использовать:

[зг19]

это самое трудное, что надо, хотя, так, вероятно, вы создали только [dадувных подушек безопасности f105] параметр, потому что export "notif_$2=$(date +%s)" трудно читать. ref="$(date +%s)" это хоть и просто,, так что вы можете пропустить строку x1= и пишите:

local -n ref="notif_$2" ref="$(date +%s)" export "${!ref}=$ref"

мне кажется, что вы могли бы использовать [то f109] просто присвоить параметр для использования в командной строке. Если вы на самом деле не нужно экспортировать его в дочерние процессы, то вы можете просто использовать первые две строки, и это проще, чем у вас.

[d63, как если вам нужно экспортировать его, используйте все три. Это все-таки немного сложнее, чем то, что вы... но она может позволить вам упростить остальные функции, потому что, после этого:[!d63, как] вместо того, чтобы писать notif_$2, вы можете просто написать [из нержавеющей стали f111 имеет]. Это работает даже в тех случаях, когда писать notif_$2 неадекватов. То есть, это уже не нужно делать ничего особенного (как способ 1 и способ 2 выше), чтобы расширить параметр, имя которого является результатом расширения notif_$2. Просто напишите ref. Это работает даже для написания-и создание, и отключения -- параметр. (После точки объявления, [115 этаж] пишет и даже может создать ссылается на параметр; unset ref сбрасывает ссылается на параметр.) [г70]если вы собираетесь использовать nameref на протяжении всей вашей функции, вы, возможно, захотите придумать более значимое имя, чем ref. (Лучшее название, конечно, быть определено задание, вы пишете функцию для выполнения.)[!г70]
2
ответ дан 24 July 2018 в 18:41

Другие вопросы по тегам:

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