在Bash中创建对象数组

19

在 Bash 中创建对象数组是否可行?

这是我的尝试:

declare -a identifications=(
  {
    email    = '...',
    password = '...'
  }
)

declare -a years=(
  '2011'
  '2012'
  '2013'
  '2014'
  '2015'
  '2016'
)

for identification in "${identifications[@]}"
do
  for year in "${years[@]}"
  do
    my_program --type=CNPJ --format=XLS --identification=${identification.email} --password=${identication.password} --competence=${year} --output="$identification - $year"
  done
done

显然,这不起作用,我找不到如何实现它,因为我找不到bash对象。


bash只有一种数据类型:字符串。即使是数组,也只是另一种语法引用形式,允许包含任意值(即空格)的字符串列表。(在bash 4中引入的关联数组稍微好了一些,但仍然远远不足以允许您寻找的数据结构类型。) - chepner
ksh93及其后续版本支持您所描述的变量定义。不幸的是,ksh似乎已经被放弃了,因为即使从kornshell.com指向的man页面也是死链接(而且已经有一段时间了)。我也无法为您指出如何使用您的ksh来实现该功能的文档(它可能在某个地方存在)。祝你好运。 - shellter
2个回答

45

你可以使用Bash 4.0中引入的关联数组和命名引用(见declare的手册和Bash 4.3中第一段Shell Parameters)对内容进行一些技巧性操作:

#!/usr/bin/env bash

declare -A identification0=(
    [email]='test@abc.com'
    [password]='admin123'
)
declare -A identification1=(
    [email]='test@xyz.org'
    [password]='passwd1!'
)

declare -n identification
for identification in ${!identification@}; do
    echo "Email: ${identification[email]}"
    echo "Password: ${identification[password]}"
done

这将打印

Email: test@abc.com
Password: admin123
Email: test@xyz.org
Password: passwd1!

declare -A 声明一个关联数组。

技巧是将所有“对象”(关联数组)的变量名都以相同的前缀命名,比如identification${!prefix@} 符号会扩展为以 prefix 开头的所有变量名:

$ var1=
$ var2=
$ var3=
$ echo "${!var@}"
var1 var2 var3

为了访问关联数组的键值对,我们使用nameref属性声明for循环的控制变量:

declare -n identification

以便循环。

for identification in ${!identification@}; do

identification转换为可从${!identification@}中展开的实际变量。

不过,做以下类似的事情可能会更容易:

emails=('test@abc.com' 'test@xyz.org')
passwords=('admin123' 'passwd1!')
for (( i = 0; i < ${#emails[@]}; ++i )); do
    echo "Email: ${emails[i]}"
    echo "Password: ${passwords[i]}"
done

也就是说,只需要循环遍历包含您信息的两个数组。


在Bash中,declare -n 标识会抛出错误,我查找了 -n 选项,但没有找到相关信息? - transformerTroy
@transformerTroy,你有Bash 4.3或更高版本吗?那是它被引入的版本。 - Benjamin W.

6

我倾向于使用JSON创建对象,因为对我来说这使得它非常容易和灵活。

这里是一个简单的例子。

我创建了一个名为devices.json的JSON文件。

{
          "backup" : [{
                "addr":"192.168.1.1",
                "username":"backuper",
                "dstfile":"firewallconfig",
                "ext":".cfg",
                "method":"ssh",
                "rotate":"no",
                "enabled":"yes"
            }, {
                "addr":"192.168.1.2",
                "username":"backuper",
                "dstfile":"routerconfig",
                "ext":".cfg",
                "method":"ssh",
                "rotate":"no",
                "enabled":"yes"
            }]
 }

Bash脚本:task.sh

 # read the devices.json file and store it in the variable jsonlist
    jsonlist=$(jq -r '.backup' "devices.json")
        # inside the loop, you cant use the fuction _jq() to get values from each object.
        for row in $(echo "${jsonlist}" | jq -r '.[] | @base64'); do
            _jq()
            {
             echo ${row} | base64 --decode | jq -r ${1}
            }
         
        echo "backing up: $(_jq '.addr')"
        echo "using method: $(_jq '.method')"
        Done

通过谷歌搜索“使用json与bash”可以找到发布原帖的人。

请问您能否发布原始帖子的链接?我在谷歌上搜索了“使用json与bash”,但没有找到。特别是我正在寻找有关函数_jq()(带下划线)的任何文档。_jq()是不是与jq()分开的单独函数,还是一些我不熟悉的bash语法? - Johnny Tisdale
1
我认为这个帖子是在这里:https://stackoverflow.com/questions/52284745/how-to-manipulate-a-jq-output-using-bash但他并没有解释太多。_jq只是我们在for循环中创建的一个函数。一开始我觉得这个for循环有点混乱,但它确实很好。 - Andrija Jostergård
1
sudo apt-get install jq Those who are getting jq: not found - Ganesh Bhosale
Done中的d是小写的。 否则,您将收到错误消息:意外的文件结尾。 - Saurabh Mhase
谢谢Saurabh Mhase。我已经纠正了。 - undefined
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接