如何在 Bash 中创建用于评估的变量

how to create a variable for evaluation in Bash

我的 CSV 文件是这样写的:

Source,Target,Database,Table,Is_deletable,Action
DBServer1,DBServer2,DB,TBL1,true,Add
DBServer2,DBServer1,DB,TBL2,true,Add

我有 shell 执行此操作的脚本:

while IFS=, read -r source target database table is_deletable action; do
    echo "Building pipeline for ${database}.${table}";
              total=$((total+1))
              Shost="server1.myorganization.com"
              Thost="server2.myorganization.com"

我需要 Shost 看起来像这样:

Shost = ${'the value of the source column'}
Thost = ${'the value of the target column'}

如何设置它以根据列数据的值动态评估我需要的变量。

例如:

Shost=${DBServer1}
Thost=${DBServer2}

然后在下一个循环中:

Shost=${DBServer2}
Thost=${DBServer1}

谢谢!

像这样的东西应该适合你:

DBServer1='server1.myorganization.com'
DBServer2='server2.myorganization.com'

while IFS=, read -r source target database table is_deletable action; do
   [[ $source = "Source" ]] && continue
   ((total++))
   Shost="${!source}"
   Thost="${!target}"

   # check variables Shost Thost total
   declare -p Shost Thost total
done < file.csv

declare -- Shost="server1.myorganization.com"
declare -- Thost="server2.myorganization.com"
declare -- total="1"
declare -- Shost="server2.myorganization.com"
declare -- Thost="server1.myorganization.com"
declare -- total="2"

在 Bash 中——但不一定在其他 shell 中——你可以间接地引用一个变量,就像你想做的那样:

$ DBServer1=db1.my.com
$ source=DBServer1
$ echo ${source}
DBServer1
$ echo ${!source}
db1.my.com

正如 Bash 手册所说 (ref):

If [in a parameter expansion of the form ${parameter}] the first character of parameter is an exclamation point (!), and parameter is not a nameref, it introduces a level of variable indirection. Bash uses the value of the variable formed from the rest of parameter as the name of the variable; this variable is then expanded and that value is used in the rest of the substitution, rather than the value of parameter itself.

将其应用于您的示例代码和数据,我们得到

DBServer1=server1.myorganization.com
DBServer2=server2.myorganization.com

# ...

while IFS=, read -r source target database table is_deletable action; do
    echo "Building pipeline for ${database}.${table}";
              total=$((total+1))
              Shost="${!source}"
              Thost="${!target}"

我们也可以使用关联数组来解决这个问题:

declare -A servers=(
    [DBServer1]='server1.myorganization.com'
    [DBServer2]='server2.myorganization.com'
)

{
    read header
    while IFS=, read -r source target database table is_deletable action; do
        Shost=${servers[$source]}
        Thost=${servers[$target]}
        ...
    done
} < file.csv