在bash中将3个独立的数组合并为一个多维数组

在bash中将3个独立的数组合并为一个多维数组

是否可以在 bash 脚本中创建多维数组?

这是我的 3 个数组:

arrayCITY=( NewYork LasVegas Detroit )
arraySTREET=( RoadStreet TreeStreet HighStreet )
arrayNUMBER=( 20 455 300 )

现在我想将这 3 个数组放入一个数组中 - 这可能吗?然后我想在txt文件中显示它们。现在我这样做:

for ((i=0; i<${#arrayCITY[*]}; i++));do
  echo "${arrayCITY[i]} ${arraySTREET[i]} ${arrayNUMBER[i]}" >> TEXT.txt
done

答案1

man 1 bash

Arrays
       Bash  provides one-dimensional indexed and associative array variables.  Any variable
       may be used as an indexed array; the  declare  builtin  will  explicitly  declare  an
       array.   There  is no maximum limit on the size of an array, nor any requirement that
       members be indexed or assigned contiguously.  Indexed  arrays  are  referenced  using
       integers  (including  arithmetic  expressions) and are zero-based; associative arrays
       are referenced using  arbitrary  strings.   Unless  otherwise  noted,  indexed  array
       indices must be non-negative integers.

关键词:

Bash 提供一维索引和关联数组变量。

所以,不,bash 不支持多维数组。

答案2

我刚才遇到了这个。有一个相当简单的解决方案对我有用。我想使用包含设备名称和屏幕位置的数组来显示设备的按键映射。我执行了以下操作:我使用分隔符将设备名称和关联的屏幕位置连接成一个字符串(在我的例子中,我使用 .)我知道它不会出现在我的任何价值观中。然后,我常常cut在需要时将复合值分解为它们的组成部分。可能有一种更干净、更简单的方法来做到这一点,但这只是为了表明您可以在某种程度上在 bash 中创建多维数组,即使它不支持它:

#!/bin/bash

# List of devices and screen positions for key maps.
DEV_LIST=( g13.+2560+30 g510s.+3160+30 g502.+2560+555 )

# This just echoes the device name and the screen position.
for DEV in "${DEV_LIST[@]}"; do
    DEVICE=$(echo $DEV | cut -f1 -d.)
    SCREEN_POSITION=$(echo $DEV | cut -f2 -d.)
    echo "$DEVICE"
    echo "$SCREEN_POSITION"
done

exit

这有点类似于Coop.Computer的回答

答案3

这是一个适合我的解决方案。如果我们首先像这样设置数组:

    arrayCSR=( Placeholder_for_0_spot NewYork RoadStreet 20 LasVegas TreeStreet 455 Detroit HighStreet 300 )

占位符的存在是为了避免处理 0 索引。

然后,每个“行”是任何可以被3整除的数字,每个“列”比“行”数字小1或2。

${arrayCSR[${3}]} is 20
${arrayCSR[${2}]} is RoadStreet
${arrayCSR[${1}]} is NewYork

示例脚本如下:

    arrayCSR=( CsR NewYork RoadStreet 20 LasVegas TreeStreet 455 Detroit HighStreet 300 )

    for p in $( seq 1 ${#arrayCSR[*]} )
    do
        if [[ "${arrayCSR[${p}]}" == "" ]] # Don't run if empty
        then
            true
        elif [[ $((p % 3 )) -eq 0 ]] # We have 3 "columns" in the array
        then
            echo " ${arrayCSR[$(( p - 2 ))]} ${arrayCSR[$(( p - 1))]} ${arrayCSR[${p}]}"
        fi
    done

因此任何能除以 3 的索引都表示一个“行”,也表示该行中的第三个“列”。要获得第二个和第一个“列”,请相应地减去 1 或 2。

如果需要的话,这也可以扩大规模。

更新:下面是我用来加载文件名的字符串替换数组的代码。第一个数组从文件加载,然后分成 2 个单独的数组。

        readarray -t string_replace < ~/scripts/string_replace.lst # List of things to remove from name
    
        for p in $( seq 0 ${#string_replace[*]} ); do
            old_name_element[${p}]="${string_replace[${p}]%%,*}"
            new_name_element[${p}]="${string_replace[${p}]:$((${#old_name_element[${p}]}+1))}"
        done
        string_replace=() # Clear old array

答案4

尽管我很喜欢 Bash,但有时切换到其他语言也是有意义的。在 Python 中使用字典非常简单:

#!/usr/bin/env python3

cities = { 
            "New York": { "Street": "Roadstreet", "Number": 20 },
            "Las Vegas": { "Street": "TreeStreet", "Number": 455 }    
         }

for city in cities:
    print(str(city) + ": " + str(cities[city]["Street"])
    + " " + str(cities[city]["Number"])) 

运行此命令会产生:

./cities.py 
New York: Roadstreet 20
Las Vegas: TreeStreet 455

相关内容