全球主机交流论坛

 找回密码
 注册

QQ登录

只需一步,快速开始

CeraNetworks网络延迟测速工具IP归属甄别会员请立即修改密码
查看: 1937|回复: 24
打印 上一主题 下一主题

shell根据数组元素获取下标

[复制链接]
跳转到指定楼层
1#
发表于 2023-3-31 22:05:50 | 只看该作者 回帖奖励 |正序浏览 |阅读模式
已知根据下标获取元素的写法是
a=(14 25 39 46 52)
echo ${a[2]}
输出结果是 39

那么根据元素如何查询该元素的对应下标呢?
25#
 楼主| 发表于 2023-4-1 19:38:13 | 只看该作者
gundam06ms 发表于 2023-4-1 18:22
看不太懂你写的,不过你的需求可以这样改。高版本的bash和其他shell(zsh、fish)有更复杂的功能。如果你 ...

看不太懂没关系,你可以试试运行一下我的脚本,能正确输出相应的结果,你的脚本也是有效的,至于说python嘛,如果在不同版本的linux下执行需要预先安装相应的python版本环境,另外,python是编程的专业工具,一般的程序需求shell脚本就能完全胜任
24#
发表于 2023-4-1 18:22:40 | 只看该作者
本帖最后由 gundam06ms 于 2023-4-1 18:25 编辑
maxkvm 发表于 2023-4-1 13:56
谢谢给出参考脚本,不过,你的脚本中的break命令直接中断了再次判断指定元素的下一次循环,因此只能判断 ...


看不太懂你写的,不过你的需求可以这样改。高版本的bash和其他shell(zsh、fish)有更复杂的功能。如果你不是一次性查找,可以使用map结构记录不然效率太差了,虽然对于shell高手来说小菜一碟,不过考虑兼容性还是建议找个python之类的语言处理...       
  1. #!/bin/bash
  2. #版本: bash 4+

  3. #声明数组foo
  4. foo=("apple" "banana" "orange" "pear" "peach" "orange"\
  5.     "melon" "coconut" "orange" "orange" "melon" "orange")
  6. #查找元素,并将所有符合的元素对应下表放入result数组
  7. element="orange"
  8. #element="pineapple"
  9. declare -a result=()

  10. for i in "${!foo[@]}"; do
  11.         if [ "${foo[$i]}" = "${element}" ]; then
  12.                 #echo "元素 ${element} 命中下标 ${i}"
  13.                 result+=(${i})
  14.         fi
  15. done

  16. if [ ${#result[@]} -eq 0 ]; then
  17.     echo "没有符合元素的下标!"
  18. else
  19.     #result[@]会把数组里所有元素展开成参数
  20.     #printf格式化打印自行百度
  21.     printf '元素 %s 命中了下标:' "${element}"
  22.     printf '%s ' "${result[@]}"
  23.     printf '\n'
  24. fi
复制代码
23#
发表于 2023-4-1 17:27:19 | 只看该作者
本帖最后由 coolloves 于 2023-4-1 17:29 编辑
maxkvm 发表于 2023-4-1 12:30
不必先转换成字典,直接遍历即可

#!/bin/bash


那要看你就是一次和多次的区别,
假如你一个数组有1w个元素,你有100个元素需要判断,就要遍历100次,转为字典只需要一次,



                                            本人专属,你瞅啥?  
    22#
     楼主| 发表于 2023-4-1 13:56:32 | 只看该作者
    gundam06ms 发表于 2023-4-1 06:07
    chatgpt给的答案没问题的,你再仔细看看,一时间也只能想到遍历一遍。

    谢谢给出参考脚本,不过,你的脚本中的break命令直接中断了再次判断指定元素的下一次循环,因此只能判断一次指定元素的下标,经过修改,脚本如下

    #!/bin/bash
    #
    fruit=("apple" "banana" "orange" "pear" "peach" "orange")
    #element="orange"
    element="watermelon"

    for i in "${!fruit[@]}"
    do
        if [ "${fruit[$i]}" == "${element}" ]
        then
            echo "元素 ${element} 的下标为 ${i}"
        fi
    done

    for i in "${!fruit[@]}"
    do
        if [ "${fruit[$i]}" == "${element}" ]
        then
            break
        fi
       
        if [ "${fruit[$i]}" != "${element}" ] && [[ $i -eq `echo $((${#fruit[@]}-1))` ]]
        then
            echo "元素 ${element}不存在,无下标"
        fi
    done

    21#
     楼主| 发表于 2023-4-1 12:30:45 | 只看该作者
    coolloves 发表于 2023-4-1 10:14
    a=(14 25 39 46 46 52)
    target=46

    不必先转换成字典,直接遍历即可

    #!/bin/bash
    #
    a=(14 25 39 46 46 52)
    value=46
    for i in ${!a[@]}
    do
        #if [[ ${a[$i]} -eq $value ]]
        if ((${a[$i]}==$value))
        then
            echo "Index of $value is $i"
        fi
    done
    20#
     楼主| 发表于 2023-4-1 12:28:01 | 只看该作者
    dvbhack 发表于 2023-4-1 10:55
    单个元素的,例如查询 "2",返回 "1"
    多个相同元素的,例如查询 "3",返回 "2,5" ...

    你的脚本真的很有大佬风范,又是函数又是传递变量参数,不过有一个最简洁明了的写法,可以同时输出相同元素的不同下标值,如下

    #!/bin/bash
    #
    a=(1 2 3 4 5 3 4)
    value=4
    #value=3
    for i in ${!a[@]}
    do
        #if [[ ${a[$i]} -eq $value ]]
        if ((${a[$i]}==$value))
        then
            echo "Index of $value is $i"
        fi
    done
    19#
     楼主| 发表于 2023-4-1 12:18:20 | 只看该作者
    irony 发表于 2023-3-31 23:15
    shell里已知数组为a=(14 25 39 46 52),那么如何获取元素39的数组下标?
    在bash shell中,您可以使用以下脚 ...

    非常感谢你使用chatgpt获取到了解答方案,不过chatgpt只能提供一个解决问题的思路,chatgpt给出的脚本有两个错误,index不需预先赋值,"${a}"是错误写法,应该是"${a[$i]}",正确的脚本如下

    #!/bin/bash
    #
    a=(14 25 39 46 52)
    value=39
    for i in ${!a[@]}
    do
        #if [[ ${a[$i]} -eq $value ]]
        if ((${a[$i]}==$value))
        then
            break
        fi
    done
    echo "Index of $value is $i"
    18#
    发表于 2023-4-1 10:55:29 | 只看该作者
    本帖最后由 dvbhack 于 2023-4-1 10:56 编辑
    1. #!/bin/bash

    2. function get_index {
    3.     local a=("$@")
    4.     local input=$1
    5.     local indices=()

    6.     for i in "${!a[@]}"; do
    7.         if [[ "${a[i]}" == "$input" ]]; then
    8.             indices+=("$i")
    9.         fi
    10.     done

    11.     if [[ ${#indices[@]} -eq 0 ]]; then
    12.         echo "-1"
    13.     else
    14.         echo "${indices[*]}"
    15.     fi
    16. }

    17. # Example usage:
    18. a=(1 2 3 4 5 3 4)
    19. idx=$(get_index "${a[@]}" 3)
    20. echo "Indices: $idx"
    复制代码


    单个元素的,例如查询 "2",返回 "1"
    多个相同元素的,例如查询 "3",返回 "2,5"
    17#
    发表于 2023-4-1 10:14:35 | 只看该作者
    本帖最后由 coolloves 于 2023-4-1 10:20 编辑

    a=(14 25 39 46 46 52)
    target=46

    declare -A map
    for i in "${!a[@]}"; do
      if [ ${map[${a[$i]}]+_} ]; then
        map["${a[$i]}"]="${map[${a[$i]}]},$i"
      else
        map["${a[$i]}"]=$i
      fi
    done

    if [ ${map[$target]+_} ]; then
      echo "Target $target found at index ${map[$target]}"
    else
      echo "Target $target not found in array"
    fi


    先转成字典.之后查询字典即可.
    为了考虑a中有重复数值,做个判断,把这个值的所有位置汇总下


      遍历一次是不可避免的,多次判断才有意义

                                              本人专属,你瞅啥?  
      您需要登录后才可以回帖 登录 | 注册

      本版积分规则

      Archiver|手机版|小黑屋|全球主机交流论坛

      GMT+8, 2024-5-15 20:53 , Processed in 0.092020 second(s), 10 queries , Gzip On, MemCache On.

      Powered by Discuz! X3.4

      © 2001-2023 Discuz! Team.

      快速回复 返回顶部 返回列表