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 / 问题 / 698502
Accepted
Sollosa
Sollosa
Asked: 2022-04-09 08:42:21 +0800 CST2022-04-09 08:42:21 +0800 CST 2022-04-09 08:42:21 +0800 CST

同时在 2 个数组的相同索引中回显值

  • 772

我有 2 个数组要同时在 bash 脚本中处理。第一个数组包含某种标签。第二个数组包含值,如下所示

LABELS=(label1 label2 label3 labe4 )
VALUES=(91 18 7 4)

需要的是:一个循环,它将回显 LABELS 数组 & 中的索引项,并在 VALUES 数组中该项的相应值前面,如下所示

label1 91
label2 18
label3 7
label4 4

我猜嵌套循环不起作用,我在下面尝试过,但它不会按语法工作

for label in {LABELS[@]} && value in {VALUES[@]}
do
    echo ${label} ${value}
done
bash shell-script
  • 5 5 个回答
  • 904 Views

5 个回答

  • Voted
  1. terdon
    2022-04-09T08:49:40+08:002022-04-09T08:49:40+08:00

    只需使用数字索引并通过索引引用数组元素:

    labels=(label1 label2 label3 label4)
    values=(91 18 7 4)
    
    
    for((i=0; i<"${#labels[@]}"; i++ )); do
      printf '%s: %s\n' "${labels[i]}" "${values[i]}"
    done
    

    或者,如果您使用的是相对较新的(>= 版本 4)bash 或其他支持关联数组的 shell,只需使用单个数组即可:

    declare -A values=( ["label1"]=91 ["label2"]=18 \
                        ["label3"]=7 ["label4"]=4 )
    
    for label in "${!values[@]}"; do
      printf '%s: %s\n' "$label" "${values[$label]}"
    done
    

    我将变量名称更改为小写,因为在 shell 脚本中对局部变量使用大写字母是不好的做法,因为全局环境变量按约定大写,因此在脚本中使用大写字母可能会导致变量名称冲突。

    • 4
  2. cas
    2022-04-09T18:10:27+08:002022-04-09T18:10:27+08:00

    由于您的两个数组具有完全相同的索引(0、1、2 和 3),因此您可以使用${!array[@]}迭代其中一个数组的索引(AKA 键)并使用该迭代器访问两个数组中的值。

    这适用于“索引数组”(即整数索引)和“关联数组”(字符串索引)。

    例如

    LABELS=(label1 label2 label3 labe4 )
    VALUES=(91 18 7 4)
    
    for i in "${!LABELS[@]}"; do
      echo "${LABELS[i]}" "${VALUES[i]}"
    done
    

    输出:

    label1 91
    label2 18
    label3 7
    labe4 4
    

    顺便说一句,您还可以使用这样的循环来填充关联数组,这在您不能同时读取键和值的情况下很有用,就像您的两个手动定义的数组一样:

    LABELS=(label1 label2 label3 labe4)
    VALUES=(91 18 7 4)
    
    declare -A LV # declare LV to be an associative array
    
    for i in "${!LABELS[@]}"; do
      LV["${LABELS[$i]}"]="${VALUES[$i]}";
    done
    
    declare -p LV
    

    输出:

    declare -A LV=([labe4]="4" [label3]="7" [label2]="18" [label1]="91" )
    

    从现在开始,您的脚本可以使用关联数组$LV直接访问键中的值,例如

    $ echo "${LV[label1]}"
    91
    

    您还可以使用 C 风格的 for 循环,如 @terdon 和 @NickMatteo 的答案(从 0 循环到数组的长度),但这仅适用于数组索引是数字且连续且数组中没有间隙(未定义索引)的情况.

    在许多/大多数情况下,这很好,因为数组通常是用连续的索引号定义的,但在其他情况下,它不会按预期工作 - 例如,如果为 1、3、5、7、11、13、17$array定义了索引然后${#array[@]}将返回 7 并且这样的循环将从 0..6 (如果您使用<=而不是<作为测试条件,则为 0..7 )而不是数组中的实际索引列表进行迭代。

    例如:

    $ for i in 1 3 5 7 11 13 17 ; do let array[$i]=$i*$i ; done
    
    $ declare -p array
    declare -a array=([1]="1" [3]="9" [5]="25" [7]="49" [11]="121" [13]="169" [17]="289")
    
    $ echo "${#array[@]}"
    7
    
    $ for ((i=0; i<"${#array[@]}"; i++)); do echo $i: "${array[$i]}" ; done
    0: 
    1: 1
    2: 
    3: 9
    4: 
    5: 25
    6: 
    
    $ echo "${!array[@]}"
    1 3 5 7 11 13 17
    
    $ for i in "${!array[@]}"; do echo $i: "${array[$i]}"; done
    1: 1
    3: 9
    5: 25
    7: 49
    11: 121
    13: 169
    17: 289
    
    • 4
  3. Best Answer
    Nick Matteo
    2022-04-09T08:48:53+08:002022-04-09T08:48:53+08:00

    只需遍历索引。例如

    for (( i = 0; i < "${#LABELS[@]}"; i++ ))
    do echo "${LABELS[$i]} ${VALUES[$i]}"
    done
    

    而不是echo,您可以使用printf更多的格式控制,例如

    printf '%6s: %3d\n' "${LABELS[$i]}" "${VALUES[$i]}"
    

    排列最多 6 个字母和最多 3 位数字的标签。

    • 3
  4. Stéphane Chazelas
    2022-04-09T10:48:21+08:002022-04-09T10:48:21+08:00

    对于那些不必使用bash,zsh使用其${arrayA:^arrayB} 数组压缩运算符的人:

    $ labels=(label1 label2 label3 labe4 )
    $ values=(91 18 7 4)
    $ for k v (${labels:^values}) print -r -- "$k => $v"
    label1 => 91
    label2 => 18
    label3 => 7
    labe4 => 4
    

    虽然你甚至不需要循环:

    $ print -raC2 -- ${labels:^values}
    label1  91
    label2  18
    label3  7
    labe4   4
    

    print他们在rolumns上交叉。a2 C

    $ printf '%6s => %d\n' ${labels:^values}
    label1 => 91
    label2 => 18
    label3 => 7
     labe4 => 4
    

    不过,在这里你也可以这样做:

    $ print -rC2 -- $labels $values
    label1  91
    label2  18
    label3  7
    labe4   4
    

    对于olumns上print的这两个数组raw (此处省略)。2 C-a

    请注意,您可以使用以下方法从这两个数组中创建一个关联数组(听起来在这里更有意义):

    typeset -A assoc
    assoc=( ${labels:^values} )
    

    如果标签或值可能包含空字符串,您宁愿使用:

    assoc=( "${(@)labels:^values}" )
    

    保存它们。

    接着:

    print -raC2 -- ${(kv)assoc}
    

    对于print keys 和 alues vaw r,a在2 Columns 上交叉,或保留空键/值:

    print -raC2 -- "${(@kv)assoc}"
    

    或者:

    for key value ("${(@kv)assoc}") print -r -- "$key => value"
    

    或者:

    for key ("${(@k)assoc}") print -r -- "$key => $assoc[$key]"
    

    但请注意,关联数组项的展开顺序未指定。

    • 3
  5. Kusalananda
    2022-04-09T14:00:25+08:002022-04-09T14:00:25+08:00

    将其中一个数组复制到一组位置参数,然后$1在循环中使用以访问其中的第一个。使用shift,第一个位置参数从列表中移出,之前的第二个元素变成了第一个。

    LABELS=(label1 label2 label3 labe4 )
    VALUES=(91 18 7 4)
    
    set -- "${VALUES[@]}"
    
    for label in "${LABELS[@]}"; do
        printf '%s\t%s\n' "$label" "$1"
        shift
    done
    

    这避免了使用索引来获取循环内的数组元素。

    输出(制表符分隔):

    label1  91
    label2  18
    label3  7
    labe4   4
    
    • 3

相关问题

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

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

  • MySQL Select with function IN () with bash array

  • `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