bash 是否支持使用指针?

bash 是否支持使用指针?

简单的问题。 bash shell 是否支持在编写 shell 脚本时使用指针?

${var[@]}在迭代数组时,我熟悉扩展符号$var,但不清楚这是利用指针迭代数组索引。 bash 是否像其他语言一样提供对内存地址的访问?

如果 bash 不支持使用指针,其他 shell 会做什么?

答案1

一个指针(指向某个位置记忆) 在任何比 C 更高级别的东西中都不是一个真正有用的概念,无论是 Python 还是 shell。对对象的引用在高级语言中当然很有用,甚至可能是构建复杂数据结构所必需的。但在大多数情况下,根据内存地址进行思考的层次太低,没有多大用处。

在 Bash(和其他 shell)中,您可以使用 符号获取数组元素的值${array[index]},使用 对其进行赋值array[index]=...,并使用 获取数组中的元素数量${#array[@]}。括号内的表达式是算术表达式。作为一个虚构的例子,我们可以为所有数组成员添加一个常量前缀:

for ((i=0 ; i < ${#array[@]} ; i++ )) ; do
    array[i]="foo-${array[i]}"
done

(如果我们只关心值,而不关心索引,那for x in "${array[@]}" ; do...就没问题了。)

联想性的或稀疏数组,数字循环没有多大意义,但我们需要使用 来获取数组键/索引${!array[@]}。例如

declare -A assoc=([foo]="123" [bar]="456")
for i in "${!assoc[@]}" ; do 
    echo "${assoc[$i]}"
done 

除此之外,Bash 有两种方法间接指向另一个变量:

  • 间接扩张, 使用语法${!var},它使用变量的值,该变量的值姓名是在var, 并且
  • 名称引用,需要用declare内置(或ksh-兼容同义词,typeset)。declare -n ref=var引用ref变量var

Namerefs 还支持索引,因为如果我们有arr=(a b c); declare -n ref=arr;then${ref[1]}将扩展到b.使用${!p[1]}p作为一个数组,并引用由其第二个元素命名的变量。

在 Bash 中,namerefs 的字面意思是,引用姓名,并且在函数内部使用 nameref 将使用指定变量的本地值。这将打印local value of var.

#!/bin/bash
fun() {
        local var="local value of var"
        echo "$ref";
}
var="global var"
declare -n ref=var
fun

Bash常见问题解答有关于间接的较长文章, 也。

答案2

不,bash没有“指针”,但它确实有引用:

$ spam="fred"
$ declare -n tripe=spam
$ echo $tripe
fred
$ tripe=juki
$ echo $spam
juki

bash手册页:

declare可以使用内置命令的 -n 选项来为变量分配 nameref 属性,local以创建 nameref 或对另一个变量的引用。这允许间接操纵变量。每当 nameref 变量被引用、赋值、取消设置或修改其属性(除了使用或更改 nameref 属性本身)时,实际上都会对 nameref 变量的值指定的变量执行操作。 nameref 通常在 shell 函数中使用来引用其名称作为参数传递给函数的变量。例如,如果将变量名作为第一个参数传递给 shell 函数,则运行

declare -n ref=$1

函数内部创建一个 nameref 变量 ref,其值是作为第一个参数传递的变量名称。对 ref 的引用和赋值以及对其属性的更改均被视为对名称作为 $1 传递的变量的引用、赋值和属性修改。如果 for 循环中的控制变量具有 nameref 属性,则单词列表可以是 shell 变量列表,并且在执行循环时将为列表中的每个单词建立名称引用。不能为数组变量赋予 nameref 属性。但是,nameref 变量可以引用数组变量和下标数组变量。可以使用内置的 -n 选项取消设置 Namerefs unset。否则,如果unset使用 nameref 变量的名称作为参数执行,则 nameref 变量引用的变量将被取消设置。

答案3

不,shell 不使用“指针”(如 C 中所理解的)。

数组可以使用索引:echo "${array[2]}"但是@您的示例中的 并不是真正的“指针”。它是一种表达“数组值列表”的方式。 shell 解析器可以理解的东西。类似于a的方式:

$ echo "$@"

展开至所有“位置参数”列表。

答案4

虽然 bash 整数索引数组可以像这样定义和迭代访问;

declare -a obj
obj+=("val1")
obj+=("val2")

for item in ${obj[@]}; do
  echo "${obj[${item}]} ${item}"
done

bash 中基于关联或字符串的索引数组需要以下迭代定义;

declare -A obj
obj["key1"]="val1"
obj["key2"]="val2"

for item in ${!obj[@]}; do
  echo "${obj[${item}]} ${item}"
done

回答有关指针和使用 bash 中的指针的问题;已编译的 bash 二进制文件的内部功能确实使用了指向堆栈上分配的内存的指针,并且确实通过使用eval.参见[间接引用]http://tldp.org/LDP/abs/html/ivr.html

有龙;eval由于安全隐患,应谨慎使用

相关内容