【问题标题】:ksh array over records记录上的 ksh 数组
【发布时间】:2018-02-26 09:10:01
【问题描述】:

我需要根据这个表关联值。

KEYS    VALS
----    ----
keyp    val1
keyp    val2
keyp    val3
keyp    val6
keyc    val4
keym    val4
keys    val8
keyr    val8
keyb    val5

在我的 ksh 中,当传递一个作为 KEY 的参数时,我想遍历该表,以便获得所有可能的 VALS。 例如,如果 parm_key="keyp",我的迭代将产生 val1、val2、val3、val6。 伪代码:

for iLoop in "${!KEYS2VALS[@]}"
do
    if [[ KEYS2VALS[iLoop] = $parm_key ]];then
        print "found value match=$KEYS2VALS[iLoop].VAL"
    fi
done

如果 $parm_key="keyp"

则该伪代码的输出应如下所示
found value match=val1
found value match=val2
found value match=val3
found value match=val6

【问题讨论】:

  • 这个“表”是从哪里来的……文件、数据库或其他东西?你是如何填充你的数组的?你有什么问题?
  • 表格将由我自己输入键/值对手动填充。没有源文件或数据库。我的问题是如何在 ksh 脚本中使用数组来实现这一点?

标签: arrays ksh records


【解决方案1】:

假设您可以访问 ksh93(所以我们可以使用关联数组)...

注意:对于一些较新的操作系统 /bin/ksh ksh93(重命名或符号链接到 ksh93);在这种情况下,ksh --version 将显示一个包含 93u93u+ 的字符串

从包含所需键/值对的平面文件开始:

# sample data file
$ cat key.vals
keyp val1
keyp val2
keyp val3
keyp val6
keyc val4
keym val4
keys val8
keyr val8
keyb val5

一个可能的 ksh93 shell 脚本:

$ cat kv
#!/bin/ksh93

# grab and verify an input key

parm_key=$1
[[ "${parm_key}" = '' ]] && printf "Usage: kv <parm_key>\n" && exit

# declare associative array 'keys2vals'

unset      keys2vals
typeset -A keys2vals

# load the key/value pairs into the associative array 'keys2vals'

while read -r key val
do
        keys2vals[${key}]="${keys2vals[${key}]} ${val}"
done < key.vals

# for debug purposes only: display array

printf "All key/value pairs:\n\n"
for key in ${!keys2vals[@]}
do
        echo "key=${key} : value=${keys2vals[${key}]}"
done
echo ""

# print the values associated with ${parm_key}

printf "All values for key = ${parm_key}:\n\n"
for val in ${keys2vals[${parm_key}]}
do
        echo "found value match=${val}"
done

正在运行的脚本:

$ kv
Usage: kv <parm_key>

$ kv keyp
All key/value pairs:

key=keyb : value= val5
key=keyc : value= val4
key=keym : value= val4
key=keyp : value= val1 val2 val3 val6
key=keyr : value= val8
key=keys : value= val8

All values for key = keyp:

found value match=val1
found value match=val2
found value match=val3
found value match=val6

# commenting out the debug loop ...

$ kv keyb
All values for key = keyb:

found value match=val5

$ kv keyc
All values for key = keyc:

found value match=val4

$ kv keym
All values for key = keym:

found value match=val4

$ kv keyr
All values for key = keyr:

found value match=val8

$ kv keys
All values for key = keys:

found value match=val8

【讨论】:

    【解决方案2】:

    我设法让二维关联数组适用于这个例子:

    首先,让我们将这些数据放入一个文件中

    $ cat table.txt
    KEYS    VALS
    ----    ----
    keyp    val1
    keyp    val2
    keyp    val3
    keyp    val6
    keyc    val4
    keym    val4
    keys    val8
    keyr    val8
    keyb    val5
    

    我们将使用一个名为“table”的关联数组

    typeset -A table
    

    现在,让我们填充数组。这里棘手的一点是我们需要声明数组的每个元素本身就是一个关联数组。当我们遇到不在“table”中的键时,我们需要这样做:

    i=0
    sed '1,2d' table.txt | while read -r key value; do
        [[ -z "${table[$key]+not set}" ]] && typeset -A table[$key]
        table[$key][$value]=$((++i))
    done
    

    现在,让我们看看表格数组中有什么

    for key in "${!table[@]}"; do 
        for subkey in "${!table[$key][@]}"; do 
            printf "%s\t%s\t%s\n" "$key" "$subkey" "${table[$key][$subkey]}"
        done
    done
    
    keyb    0   
    keyb    val5    9
    keyc    0   
    keyc    val4    5
    keym    0   
    keym    val4    6
    keyp    0   
    keyp    val1    1
    keyp    val2    2
    keyp    val3    3
    keyp    val6    4
    keyr    0   
    keyr    val8    8
    keys    0   
    keys    val8    7
    

    一切都很好,除了每个顶级键还有一个子键“0”。这看起来很奇怪,但我认为这就是在 ksh 中实现变量的方式。即使是简单的标量变量也可以引用为索引为 0 的数组:

    $ foo=bar
    $ echo "$foo"
    bar
    $ echo "${foo[0]}"
    bar
    $ printf "%s\n" "${!foo[@]}"
    0
    

    问题的核心:检索特定键的值:

    parm_key="keyp"
    typeset -a values
    for val in "${!table[$parm_key][@]}"; do
        [[ $val = "0" ]] || values+=("$val")
    done
    printf "%s\n" "${values[@]}"
    
    val1
    val2
    val3
    val6
    

    我刚刚意识到这太复杂了。我们不需要关联数组的关联数组。我们想要一个索引数组的关联数组:

    $ unset table
    $ typeset -A table
    $ sed '1,2d' table.txt | while read -r key value; do table[$key]+=("$value"); done
    $ printf "%s\n" "${!table[@]}"
    keyb
    keyc
    keym
    keyp
    keyr
    keys
    $ for key in "${!table[@]}"; do for val in "${table[$key][@]}"; do printf "%s\t%s\n" "$key" "$val"; done; done
    keyb    val5
    keyc    val4
    keym    val4
    keyp    val1
    keyp    val2
    keyp    val3
    keyp    val6
    keyr    val8
    keys    val8
    $ printf "%s\n" "${table[$parm_key][@]}"
    val1
    val2
    val3
    val6
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-05-22
      • 1970-01-01
      • 1970-01-01
      • 2022-08-20
      • 2013-05-25
      • 2020-09-07
      • 2021-12-05
      相关资源
      最近更新 更多