AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / unix / 问题 / 755111
Accepted
John Smith
John Smith
Asked: 2023-08-28 17:10:35 +0800 CST2023-08-28 17:10:35 +0800 CST 2023-08-28 17:10:35 +0800 CST

如何从数组数组中选择要循环的数组?

  • 772
#!/usr/bin/bash


ARGENT=("Nous devons économiser de l'argent."
"Je dois économiser de l'argent.")

BIENETRE=("Comment vas-tu?" "Tout va bien ?")

aoarrs=("${ARGENT}" "${BIENETRE}")

select arr in "${aoarrs[@]}"; do
  for el in "${arr[@]}"; do
    echo "$el"
  done
  break
done 

我希望此脚本将数组名称打印给用户ARGENT和BIENETRE,以便用户可以选择其中之一。用户输入后,脚本将打印所选数组的每个元素。我想从数组的数组 ( ) 中选择select一个数组来循环aoarrs。我想使用 select 的原因是因为在现实世界中,我的数组数组中可能不止两个数组。我怎样才能做到这一点?

bash
  • 4 4 个回答
  • 786 Views

4 个回答

  • Voted
  1. Best Answer
    glenn jackman
    2023-08-28T21:00:34+08:002023-08-28T21:00:34+08:00

    您将把数组名称存储在 中aoarrs,并在选择主体内声明所选名称的nameref:

    ARGENT=("Nous devons économiser de l'argent."
    "Je dois économiser de l'argent.")
    BIENETRE=("Comment vas-tu?" "Tout va bien ?")
    aoarrs=(ARGENT BIENETRE)
    
    PS3='Which array? '
    select arr in "${aoarrs[@]}"; do 
        [[ $arr ]] || continue
        declare -n ref=$arr
        for i in "${!ref[@]}"; do 
            printf '%d\t%s\n' $i "${ref[i]}"
        done 
        break
    done
    

    跑步可能看起来像

    1) ARGENT
    2) BIENETRE
    Which array? 3
    Which array? 4
    Which array? 5
    Which array? 2
    0   Comment vas-tu?
    1   Tout va bien ?
    
    • 5
  2. Marcus Müller
    2023-08-28T17:54:52+08:002023-08-28T17:54:52+08:00

    您需要“键”到“值”的映射,其中“值”是字符串列表,“键”ARGENT是BIENETRE……

    您走在正确的道路上aoarrs,因为您可以将该数组用作关联数组:

    declare -A aoarrs
    aoarrs[ARGENT]=$ARGENT
    aoarrs[BIENETRE]=$BIENETRE
    

    然后使用类似 的方法迭代该数组中的所有键for key in ${!aoarrs[@]}…。

    遗憾的是,无论出于何种原因,bash 都不允许列表作为这些关联数组的元素。

    所以,事情很糟糕。例如,您可以使用保留字符连接列表的元素,以便稍后分割它们(这很愚蠢,因为这意味着您不能在字符串中包含所有字符,或者需要开始转义它们),或者您构建自己的函数获取字符串列表,将它们附加到一个大数组中,然后在该容器上实现自己的关联查找函数(这将是愚蠢的;它不仅会很慢,而且还需要您在相对较大的空间中编写相对较多的代码)语言不合适)。看起来会很糟糕。这是一个我在没有测试的情况下写下来的例子,因为它太丑陋了,我需要把它从我的脑海中清除,但不想再进一步处理它:

    #!/bin/bash
    ###############################
    #        UNTESTED STUFF       #
    # If you think this code is   #
    # acceptable, consider doing  #
    # something good for yourself #
    # once in a while             #
    ###############################
    declare -A index
    declare -A lengths
    declare -a storage
    
    # Adds an entry to our our custom container
    # 
    # Usage:
    # add_key_values KEY "list element 1" "list element 2" …
    function add_key_values() {
      local key="$1"
      shift
      local -n valuelist=$@
    
      # get the length of the passed list, to save it
      local lengthlist=${#valuelist[@]}
    
    
      # get the end of the current storage, that's where we start adding
      # our list
      local start_index=${#storage[@]}
    
      # finally, actually store the list items in the storage
      for item in "${valuelist[@]}"; do
        storage+=("${item}")
      done
      lengths["${key}"]=$lengthlist
      index["${key}"]=$start_index
    }
    
    # Retrieve a list from the storage
    # Sadly, bash is not a proper programming language, because what it calls
    # "functions" don't do the one thing that a function needs to do:
    # return a value for an argument. There's just no "return" mechanism in bash.
    # 
    # Returns an empty list if the key wasn't found.
    #
    # So, after sobbing a bit, we just say
    # Usage:
    # get_values $key
    # Overwrites the `ret_val` variable with the list that was saved earlier
    function get_values() {
      # prepare ret_val
      declare -g -a ret_val=()
    
      local key=$1
    
      # We return (with ret_val empty) if key isn't present
      # frigging bash doesn't have a "is key present in associative array" function…
      # so this is the workaround to check whether there's $key in $index.
      # seriously.
      local teststring
      teststring="$(printf 'index[%s]' "${key}")"
      # you need quite modern bash to even get the "is defined" -v test
      [[ -v "${teststring}" ]] || return
    
      # let's get all the elements from storage and append them to ret_val
      local start=${index[$key]}
      local length=${lengths[$key]}
      for idx in $(seq $(( start - 1 )) $((start - 1 + length)) ); do 
        ret_val+=("${storage[idx]}")
      done
    }
    
    ####################
    # EXAMPLE USAGE
    ####################
    add_key_values "ARGENT" "Nous devons économiser de l'argent." "Je dois économiser de l'argent."
    add_key_values "BIENETRE" ("Comment vas-tu?" "Tout va bien ?")
    
    for key in ${!index[@]}; do
      echo "the list for value $key contains"
      get_values "${key}"
      for element in ${ret_val[@]}; do
        echo "element: ${element}"
      done
    done
    
    

    下一个选项很神奇,涉及使用 . 按名称“间接寻址”变量eval。这是一种邪恶、愚蠢的行为,这里有很多帖子暗示“如果你到了那个时候,那么也许可以使用适当的编程语言而不是 bash”。

    我同意这一点:整个问题实际上可以用四行 python 来完成,前两行将把“ARGENT”和“BIENETRE”及其列表存储到一个dict. 或者实际上,在除 bash(或 C,就此而言)之外的任何其他通用语言中,关联数组都没有那么糟糕。

    • 2
  3. nezabudka
    2023-08-28T21:11:32+08:002023-08-28T21:11:32+08:00

    生成数组仅包含变量名称:

    aoarrs=(ARGENT BIENETRE)
    
    while :; do
            select arr in "${aoarrs[@]}" quit; do
                    declare -n ref=$arr
                    case $arr in
                            quit)
                                    break 2;; 
                            *)
                                    select item in "${ref[@]}"; do
                                            echo $item
                                            break
                                    done;;
                    esac
                    break
            done
    done
    

    declare -n ref=$arr-引用由其值命名的变量。
    break 2-打破 2 个封闭循环。

    • 1
  4. Stéphane Chazelas
    2023-08-28T23:13:02+08:002023-08-28T23:13:02+08:00

    在 ksh93(shell bash 尝试模拟)中会更容易,其中关联数组可以将数组(除其他外)作为值。

    #! /bin/ksh -
    
    typeset -A all=(
      [argent]=(
        "Nous devons économiser de l'argent."
        "Je dois économiser de l'argent."
      )
    
      [bien-être]=(
        "Comment vas-tu?"
        "Tout va bien ?"
      )
    )
    
    select topic in "${!all[@]}"; do
      for sentence in "${all[$topic][@]}"; do
        print -r -- "$sentence"
      done
      break
    done
    
    • 1

相关问题

  • 通过命令的标准输出以编程方式导出环境变量[重复]

  • 从文本文件传递变量的奇怪问题

  • 虽然行读取保持转义空间?

  • `tee` 和 `bash` 进程替换顺序

  • 运行一个非常慢的脚本直到它成功

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    模块 i915 可能缺少固件 /lib/firmware/i915/*

    • 3 个回答
  • Marko Smith

    无法获取 jessie backports 存储库

    • 4 个回答
  • Marko Smith

    如何将 GPG 私钥和公钥导出到文件

    • 4 个回答
  • Marko Smith

    我们如何运行存储在变量中的命令?

    • 5 个回答
  • Marko Smith

    如何配置 systemd-resolved 和 systemd-networkd 以使用本地 DNS 服务器来解析本地域和远程 DNS 服务器来解析远程域?

    • 3 个回答
  • Marko Smith

    dist-upgrade 后 Kali Linux 中的 apt-get update 错误 [重复]

    • 2 个回答
  • Marko Smith

    如何从 systemctl 服务日志中查看最新的 x 行

    • 5 个回答
  • Marko Smith

    Nano - 跳转到文件末尾

    • 8 个回答
  • Marko Smith

    grub 错误:你需要先加载内核

    • 4 个回答
  • Marko Smith

    如何下载软件包而不是使用 apt-get 命令安装它?

    • 7 个回答
  • Martin Hope
    user12345 无法获取 jessie backports 存储库 2019-03-27 04:39:28 +0800 CST
  • Martin Hope
    Carl 为什么大多数 systemd 示例都包含 WantedBy=multi-user.target? 2019-03-15 11:49:25 +0800 CST
  • Martin Hope
    rocky 如何将 GPG 私钥和公钥导出到文件 2018-11-16 05:36:15 +0800 CST
  • Martin Hope
    Evan Carroll systemctl 状态显示:“状态:降级” 2018-06-03 18:48:17 +0800 CST
  • Martin Hope
    Tim 我们如何运行存储在变量中的命令? 2018-05-21 04:46:29 +0800 CST
  • Martin Hope
    Ankur S 为什么 /dev/null 是一个文件?为什么它的功能不作为一个简单的程序来实现? 2018-04-17 07:28:04 +0800 CST
  • Martin Hope
    user3191334 如何从 systemctl 服务日志中查看最新的 x 行 2018-02-07 00:14:16 +0800 CST
  • Martin Hope
    Marko Pacak Nano - 跳转到文件末尾 2018-02-01 01:53:03 +0800 CST
  • Martin Hope
    Kidburla 为什么真假这么大? 2018-01-26 12:14:47 +0800 CST
  • Martin Hope
    Christos Baziotis 在一个巨大的(70GB)、一行、文本文件中替换字符串 2017-12-30 06:58:33 +0800 CST

热门标签

linux bash debian shell-script text-processing ubuntu centos shell awk ssh

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve