全球主机交流论坛

标题: shell根据数组元素获取下标 [打印本页]

作者: maxkvm    时间: 2023-3-31 22:05
标题: shell根据数组元素获取下标
已知根据下标获取元素的写法是
a=(14 25 39 46 52)
echo ${a[2]}
输出结果是 39

那么根据元素如何查询该元素的对应下标呢?
作者: heihai    时间: 2023-3-31 22:08
不同下标相同数据呢,要怎么判断
作者: maxkvm    时间: 2023-3-31 22:09
heihai 发表于 2023-3-31 22:08
不同下标相同数据呢,要怎么判断

输出两个不同的下标值
作者: HOH    时间: 2023-3-31 22:10
这位同学,我布置的作业请自己完成
作者: maxkvm    时间: 2023-3-31 22:12
HOH 发表于 2023-3-31 22:10
这位同学,我布置的作业请自己完成

不会就不要凑热闹
作者: yanzhiling2002    时间: 2023-3-31 22:17
计算机的排序是从0开始的,不是常识中的1.

你看到的a2 ,在计算机执行里,是第三个数。

a=(14 25 39 46 52)

a0 =14
a1 =25
a2 =39
作者: maxkvm    时间: 2023-3-31 22:19
yanzhiling2002 发表于 2023-3-31 22:17
计算机的排序是从0开始的,不是常识中的1.

你看到的a2 ,在计算机执行里,是第三个数。

我没说错啊,下标2对应的元素是39
作者: yanzhiling2002    时间: 2023-3-31 22:25
maxkvm 发表于 2023-3-31 22:19
我没说错啊,下标2对应的元素是39

不好意思,没看清楚要求

我能想到的就是键值对用shell操作比较麻烦
作者: yanzhiling2002    时间: 2023-3-31 22:28
我给你问了一下chatgpt

在shell中,可以使用数组来存储元素,并使用循环结构来查找元素对应的下标。 例如,下面的脚本演示了如何使用循环结构查找数组中指定元素的下标:
shell
#!/bin/bash

# 定义一个数组
array=("apple" "banana" "orange" "pear" "peach")

# 需要查找的元素
element="orange"

# 使用循环结构查找元素
for i in "${!array[@]}"; do
  if [[ "${array[$i]}" = "${element}" ]]; then
    echo "元素 ${element} 的下标为 ${i}"
    break
  fi
done
在上述脚本中,首先定义了一个数组`array`,然后定义了需要查找的元素`element`。接着,使用`for`循环遍历数组中的每个元素,使用`if`语句判断当前元素是否为需要查找的元素,如果是,则输出该元素的下标,并使用`break`语句跳出循环。 需要注意的是,在`for`循环中,使用`${!array[@]}`来获取数组中所有元素的下标。`${array[$i]}`表示获取数组中下标为`$i`的元素的值。 如果需要查找数组中所有符合条件的元素的下标,可以将`break`语句删除,并将输出语句改为打印所有符合条件的元素的下标。
作者: gundam06ms    时间: 2023-3-31 22:29
你说的不清不楚,会重复吗?是大小排列好的么?
作者: silence    时间: 2023-3-31 22:35
遍历再判断一下呗,没有好的方法
作者: maxkvm    时间: 2023-3-31 22:39
gundam06ms 发表于 2023-3-31 22:29
你说的不清不楚,会重复吗?是大小排列好的么?

不必大小排列,就是我说的自定义排列
作者: maxkvm    时间: 2023-3-31 22:40
yanzhiling2002 发表于 2023-3-31 22:25
不好意思,没看清楚要求

我能想到的就是键值对用shell操作比较麻烦

所以根据元素求下标是没有这种操作吗?
作者: maxkvm    时间: 2023-3-31 22:42
yanzhiling2002 发表于 2023-3-31 22:28
我给你问了一下chatgpt

在shell中,可以使用数组来存储元素,并使用循环结构来查找元素对应的下标。 例如 ...

chatgpt完全帮不上忙,它说的还是根据下标求元素,这个不用它来回答,反过来根据元素求下标呢?
作者: irony    时间: 2023-3-31 23:15
maxkvm 发表于 2023-3-31 22:42
chatgpt完全帮不上忙,它说的还是根据下标求元素,这个不用它来回答,反过来根据元素求下标呢? ...

shell里已知数组为a=(14 25 39 46 52),那么如何获取元素39的数组下标?
在bash shell中,您可以使用以下脚本找到数组中特定值的索引:

a=(14 25 39 46 52)
value=39
index=-1

for i in "${!a[@]}"; do
    if [ "${a}" -eq "$value" ]; then
        index=$i
        break
    fi
done

echo "Index of $value is $index"

这个脚本首先定义了一个数组a和一个要查找的值value。我们将index初始化为-1,表示尚未找到该值。然后,我们用for循环遍历数组,并使用${!a[@]}获取数组的所有索引。当找到等于value的元素时,我们将index设置为当前索引并退出循环。最后,我们输出找到的索引。在这个例子中,它将输出Index of 39 is 2,因为39位于数组的第2个位置(索引从0开始)。

答案跟上边类似的,就是先把元素遍历出来然后再依次去比较,没想到还挺麻烦的,shell里的编程根本懒得记,以后都去问chatgpt好了
作者: gundam06ms    时间: 2023-4-1 06:07
本帖最后由 gundam06ms 于 2023-4-1 06:21 编辑
maxkvm 发表于 2023-3-31 22:42
chatgpt完全帮不上忙,它说的还是根据下标求元素,这个不用它来回答,反过来根据元素求下标呢? ...


chatgpt给的答案没问题的,你再仔细看看,一时间也只能想到遍历一遍。
  1. #!/bin/bash

  2. #声明数组
  3. foo=("apple" "banana" "orange" "pear" "peach" "orange")
  4. #查找叫做"orange"的元素(遍历数组,如果元素第一次出现即返回结果)
  5. element="orange"
  6. #found为1说明没找到,found为0说明找到了
  7. found=1
  8. for i in "${!foo[@]}"; do
  9.         #$i 是数组下标
  10.         #${foo[i]} 是foo[i]对应元素
  11.         if [[ "${foo[$i]}" = "${element}" ]]; then
  12.                 echo "元素 ${element} 的下标为 ${i}" && found=0 && break
  13.         fi
  14. done
  15. if [[ "${found}" -ne 0 ]]; then echo "没有找到元素 ${element}"; fi
复制代码


不同的shell和版本语法有不同的地方,更复杂的任务建议用python处理了。
作者: coolloves    时间: 2023-4-1 10:14
本帖最后由 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中有重复数值,做个判断,把这个值的所有位置汇总下


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

                                        本人专属,你瞅啥?  
作者: dvbhack    时间: 2023-4-1 10:55
本帖最后由 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"
作者: maxkvm    时间: 2023-4-1 12:18
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"

作者: maxkvm    时间: 2023-4-1 12:28
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
作者: maxkvm    时间: 2023-4-1 12:30
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
作者: maxkvm    时间: 2023-4-1 13:56
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


作者: coolloves    时间: 2023-4-1 17:27
本帖最后由 coolloves 于 2023-4-1 17:29 编辑
maxkvm 发表于 2023-4-1 12:30
不必先转换成字典,直接遍历即可

#!/bin/bash


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



                                            本人专属,你瞅啥?  
    作者: gundam06ms    时间: 2023-4-1 18:22
    本帖最后由 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
    复制代码

    作者: maxkvm    时间: 2023-4-1 19:38
    gundam06ms 发表于 2023-4-1 18:22
    看不太懂你写的,不过你的需求可以这样改。高版本的bash和其他shell(zsh、fish)有更复杂的功能。如果你 ...

    看不太懂没关系,你可以试试运行一下我的脚本,能正确输出相应的结果,你的脚本也是有效的,至于说python嘛,如果在不同版本的linux下执行需要预先安装相应的python版本环境,另外,python是编程的专业工具,一般的程序需求shell脚本就能完全胜任




    欢迎光临 全球主机交流论坛 (https://443502.xyz/) Powered by Discuz! X3.4