bash 不使用 eval 的嵌套 shell 变量

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/6818948/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-18 00:26:21  来源:igfitidea点击:

nested shell variables without using eval

bashshelleval

提问by nachocab

Can I get rid of evalhere? I'm trying to set $current_databasewith the appropriate variable determined by user input (country and action)

我可以摆脱eval这里吗?我正在尝试$current_database使用由用户输入(国家和行动)确定的适当变量进行设置

# User input
country="es"
action="sales"

# Possible variables for current_database
final_es_sales_path="blahblah/es/sales.csv"
final_en_support_path="yadayada/en/support.csv"
final_it_inventory_path="humhum/it/inventory.csv"
...

current_database=$(eval echo ${final_${country}_${action}_path})

采纳答案by Diego Sevilla

You can use associative arrays, joining the value of both variables. For example:

您可以使用关联数组,连接两个变量的值。例如:

declare -A databases
# initialization
databases["es:sales"]="blahblah/es/sales.csv"
databases["en:support"]="yadayada/en/support.csv"

Then, you can get the database just by:

然后,您可以通过以下方式获取数据库:

echo ${databases["${country}:${action}"]}

This has the advantage of having the database names collected by only one variable.

这样做的好处是仅由一个变量收集数据库名称。

回答by Jesse

Actually, yes you can, and without resorting to associative arrays (which isn't a bad solution, mind you). You can use a solution similar to this:

实际上,是的,您可以,而且无需求助于关联数组(请注意,这不是一个糟糕的解决方案)。您可以使用与此类似的解决方案:

> current_database=$(echo final_${country}_${action}_path)
> echo $current_database
final_es_sales_path
> current_database=${!current_database}
> echo $current_database
blahblah/es/sales.csv

This avoids arrays and evals by using indirect expansion. This appears to have been introduced in the second version of Bash, so pretty much any machine should be able to do it.

这通过使用间接扩展避免了数组和评估。这似乎是在 Bash 的第二个版本中引入的,所以几乎任何机器都应该能够做到。

回答by Pa?lo Ebermann

Doesn't

没有

current_database=${final_${country}_${action}_path}

do what you want?

做你想做的事?

Edit: No, it does not. Parameter expansion works only on one word (for the parameter name), and $is not allowed in a word. It would be possible to use nested parameter expansion in the other parts of the more complicated versions (with limits, replacement, default value etc.), though, which is why the several expansion variants are listed here (which fooled me first) (emphasis by me):

编辑:不,它没有。参数扩展只对一个单词起作用(对于参数名称),并且$不允许在一个单词中。但是,可以在更复杂版本的其他部分(带有限制、替换、默认值等)中使用嵌套参数扩展,这就是为什么这里列出了几个扩展变体的原因(首先愚弄了我)(强调由我):

When braces are used, the matching ending brace is the first ‘}' not escaped by a backslash or within a quoted string, and not within an embedded arithmetic expansion, command substitution, or parameter expansion.

当使用大括号时,匹配的结束大括号是第一个没有被反斜杠或带引号的字符串转义的 '}',并且不在嵌入式算术扩展、命令替换或参数扩展中

Sorry. Looks like eval and arrays are your best bet, then.

对不起。那么看起来 eval 和 arrays 是你最好的选择。