百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术文章 > 正文

shell中如何逆序打印数组的内容,或者反转一个数组?

myzbx 2025-07-03 18:16 4 浏览


首先请注意,有序的概念仅适用于索引数组,而不适用于关联数组。如果没有稀疏数组,答案会更简单,但是Bash的数组可以是稀疏的(非连续索引)。因此,我们需要引入一个额外的步骤。

打印

首先,我们需要获取数组的索引。我们可以使用bash 3.0中引入的${!array[@]}语法来实现这一点。(在bash 3.0之前,我们需要对整个数组进行复制;请参见下面的内容。)

一旦我们获得了索引列表,就可以按逆序遍历该列表。然后,逐个使用得到的索引来引用原始数组。因此:

# bash 3.0 or higher
array=(world [13]=hello)
idx=("${!array[@]}")     # copy of INDICES
for (( i = ${#idx[@]} - 1; i >= 0; i-- )); do
  j=${idx[i]}
  printf "%s " "${array[j]}"
done
echo

在我们知道数组不是稀疏的退化情况下,我们可以从索引length - 1开始反向迭代原始数组,直到索引0。下一个示例将展示这一点,所以我们不在此处重复说明。

如果我们需要在旧于3.0版本的Bash中以逆序打印(稀疏)数组,那么我们可以复制整个数组以消除稀疏性,然后对复制的数组进行迭代:

# bash 2.0 or higher; less efficient
array=(world [13]=hello)
tmp=("${array[@]}")      # copy of CONTENTS
i=$(( ${#tmp[@]} - 1 ))
while ((i >= 0)); do
  printf "%s " "${tmp[i]}"
  ((i--))
done
echo

当数组需要传递给函数或已经设置了extdebug时,可以使用BASH_ARGV对数组项按逆序进行操作。(对于其他大多数情况,BASH_ARGV可能不如上面的示例高效。)。。。。。。

reverse_array()
{
  shopt -s extdebug
  f()
  {
    printf "%s " "${BASH_ARGV[@]}";
  }
  f "$@"
  shopt -u extdebug
}
a=(1 2 3 4)
reverse_array "${a[@]}"

逆转列表

如果我们将一个数组视为一个列表(忽略索引),那么我们可能希望创建一个新列表,其中包含相同的元素,但顺序相反。在这种情况下,我们不打算保留原始可能稀疏的索引。新列表将简单地按顺序从0开始索引。

与上述类似,我们希望按逆序遍历原始列表的元素。这意味着我们首先需要一个原始索引的列表。我们可以按逆序遍历这些索引,因此按逆序检索元素,并将其附加到我们的新列表(数组)中

# bash 3.0
# 将数组 a 的元素逆序存入新数组 b。
idx=("${!a[@]}")
b=()
for (( i=${#idx[@]} - 1; i >= 0; i-- )); do
  j=${idx[i]}
  b+=("${a[j]}")
done

实际上,输入数组通常是位置参数("$@"),而不是命名数组。幸运的是,bash具有间接索引语法,可以让我们通过存储在变量中的数字检索位置参数。我们还知道位置参数永远不会稀疏,因此可以跳过数组索引步骤。

# bash
# 将位置参数逆序存入新数组 rev。
rev=()
for (( i=$#; i >= 1; i-- )); do
  rev+=("${!i}")
done

# 现在可以使用 "${rev[@]}" 来传递逆序后的参数。

原地逆转一个数组

在这一部分,我们将探讨将(可能稀疏的)数组的元素彼此交换,而不是创建一个新的顺序索引数组的思想。对于稀疏数组,索引的含义将被抹去,所以这实际上并不清楚有多有用。对于非稀疏数组,这样做更有意义。但无论如何,我们继续。

基本算法是保持两个索引指针,它们分别从数组的开始和末尾开始,并向彼此移动。由于数组可能是稀疏的,我们使用上面描述的索引数组步骤

# bash 3.0
# 将数组 a 原地逆序排列。
# 构建索引 idx,保存数组 a 的指针。
idx=("${!a[@]}")
((i=0, j=${#idx[@]}-1))
while ((i < j)); do
  # 将 idx 中的指针映射为数组 a 的索引。
  ii=${idx[i]}
  jj=${idx[j]}

  # 交换数组 a 中的元素。
  t=${a[ii]}
  a[ii]=${a[jj]}
  a[jj]=$t

  # 向中间移动指针。
  ((i++, j--))
done

如果你想学习如何编写更加健壮和可靠的 Shell 脚本,减少生产环境中的错误和故障,那么关注我吧!我会分享 Shell 编程的最佳实践和建议,帮助你提高 Shell 脚本的鲁棒性和可维护性。如果你想深入了解 Shell 编程的实际应用和技巧,可以关注我的《Shell 脚本编程最佳实践》专栏,里面有我在一线互联网大厂的实际生产经验和最佳实践,帮助你高效完成各种自动化任务。

相关推荐

C语言速成之数组:C语言数据处理的核心武器,你真的玩透了吗?

程序员Feri一名12年+的程序员,做过开发带过团队创过业,擅长Java、鸿蒙、嵌入式、人工智能等开发,专注于程序员成长的那点儿事,希望在成长的路上有你相伴!君志所向,一往无前!数组:C语言数据处理...

ES6史上最全数JS数组方法合集-02-数组操作

数组生成array.ofletres=Array.of(1,2,3)console.log(res)//[1,2,3]下标定位indexOf用于查找数组中是否存在某个值,如果存...

前端性能拉胯?这 8 个 JavaScript 技巧让你的代码飞起来!

在前端开发的江湖里,JavaScript就是我们手中的“绝世宝剑”。但为啥别人用剑就能轻松斩敌,你的代码却总拖后腿,页面加载慢、交互卡顿?别着急!今天带来8个超实用的JavaScript实...

12种JavaScript中最常用的数组操作整理汇总

数组是最常见的数据结构之一,我们需要绝对自信地使用它。在这里,我将列出JavaScript中最重要的几个数组常用操作片段,包括数组长度、替换元素、去重以及许多其他内容。1、数组长度大多数人都知道可...

手把手教你在Webpack写一个Loader

前言有的时候,你可能在从零搭建Webpack项目很熟悉,配置过各种loader,面试官在Webpack方面问你,是否自己实现过一个loader?如果没有去了解过如果去实现,确实有点尴尬,其...

const关键字到底该什么用?(可以用const关键字定义变量吗)

文|守望先生经授权转载自公众号编程珠玑(id:shouwangxiansheng)前言我们都知道使用const关键字限定一个变量为只读,但它是真正意义上的只读吗?实际中又该如何使用const关键字...

“JavaScript变量声明三兄弟,你真的会用吗?

在JavaScript中,var、let和const是声明变量的关键字,它们在作用域、变量提升、重复声明和重新赋值等方面有显著区别。以下是它们的相同点和不同点,并通过代码示例详细说明。一、相同点声明变...

ES6(二)let 和 const(es6 var let const区别)

let命令let和var差不多,只是限制了有效范围。先定义后使用不管是什么编程语言,不管语法是否允许,都要秉承先定义,然后再使用的习惯,这样不会出幺蛾子。以前JavaScript比较随意,...

js 里面 let 和 const的区别(js中的let)

在JavaScript(包括Vue、Node.js、前端脚本等)中,const和let是用于声明变量的两种方式,它们的主要区别如下:constvslet的区别特性constlet是否...

JDK21新特性:Sequenced Collections

SequencedCollectionsJDK21在JEP431提出了有序集合(SequencedCollections)。引入新的接口来表示有序集合。这样的集合都有一个明确的第一个元素、第二个...

动态编程基础——第 2 部分(动态编程是什么)

有两种方法可以使用动态规划来解决问题。在这篇文章中,我们将了解制表法。请参阅我的动态编程基础——第1部分了解记忆方法。记忆制表什么是动态规划?它是一种简单递归的优化技术。它大大减少了解决给定...

Lambda 函数,你真的的了解吗(lambda函数用法)

什么是lambda函数lambda函数是一个匿名函数,这意味着与其他函数不同,它们没有名称。这是一个函数,它添加两个数字,写成一个命名函数,可以按其名称调用它们:defadd(x,y):...

JavaScript 数组操作方法大全(js数组操作的常用方法有哪些)

数组操作是JavaScript中非常重要也非常常用的技巧。本文整理了常用的数组操作方法(包括ES6的map、forEach、every、some、filter、find、from、of等)...

系列专栏(六):解构赋值(解构赋值默认值)

ES6作为新一代JavaScript标准,已正式与广大前端开发者见面。为了让大家对ES6的诸多新特性有更深入的了解,MozillaWeb开发者博客推出了《ES6InDepth》系列文章。CSDN...

js列表遍历方法解读(js遍历链表)

JavaScript提供了多种遍历数组(或列表)的方法。以下是一些常用的方法及其解读:for循环:vararray=[1,2,3,4,5];for(vari=0;...