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 / 问题 / 413449
Accepted
111---
111---
Asked: 2017-12-29 06:10:51 +0800 CST2017-12-29 06:10:51 +0800 CST 2017-12-29 06:10:51 +0800 CST

bash 是否支持使用指针?

  • 772

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

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

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

bash
  • 4 4 个回答
  • 10768 Views

4 个回答

  • Voted
  1. Best Answer
    ilkkachu
    2017-12-29T06:49:17+08:002017-12-29T06:49:17+08:00

    指针(指向内存位置)在任何比 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},它使用名称为 in的变量的值var,以及
    • namerefs,需要使用declare内置函数(或ksh兼容的同义词,typeset)创建。declare -n ref=var对变量进行ref引用var。

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

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

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

    BashFAQ 也有一篇关于间接的较长文章。

    • 28
  2. hackerb9
    2017-12-29T09:07:01+08:002017-12-29T09:07:01+08:00

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

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

    从bash手册页:

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

    declare -n ref=$1
    

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

    • 10
  3. user232326
    2017-12-29T06:19:59+08:002017-12-29T06:19:59+08:00

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

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

    $ echo "$@"
    

    扩展到所有“位置参数”列表。

    • 4
  4. jas-
    2017-12-29T07:29:08+08:002017-12-29T07:29:08+08:00

    虽然可以像这样迭代地定义和访问 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应谨慎使用

    • 2

相关问题

  • 通过命令的标准输出以编程方式导出环境变量[重复]

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

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

  • `tee` 和 `bash` 进程替换顺序

  • 运行一个非常慢的脚本直到它成功

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    JSON数组使用jq来bash变量

    • 4 个回答
  • Marko Smith

    日期可以为 GMT 时区格式化当前时间吗?[复制]

    • 2 个回答
  • Marko Smith

    bash + 通过 bash 脚本从文件中读取变量和值

    • 4 个回答
  • Marko Smith

    如何复制目录并在同一命令中重命名它?

    • 4 个回答
  • Marko Smith

    ssh 连接。X11 连接因身份验证错误而被拒绝

    • 3 个回答
  • Marko Smith

    如何下载软件包而不是使用 apt-get 命令安装它?

    • 7 个回答
  • Marko Smith

    systemctl 命令在 RHEL 6 中不起作用

    • 3 个回答
  • Marko Smith

    rsync 端口 22 和 873 使用

    • 2 个回答
  • Marko Smith

    以 100% 的利用率捕捉 /dev/loop -- 没有可用空间

    • 1 个回答
  • Marko Smith

    jq 打印子对象中所有的键和值

    • 2 个回答
  • Martin Hope
    EHerman JSON数组使用jq来bash变量 2017-12-31 14:50:58 +0800 CST
  • Martin Hope
    Christos Baziotis 在一个巨大的(70GB)、一行、文本文件中替换字符串 2017-12-30 06:58:33 +0800 CST
  • Martin Hope
    Drux 日期可以为 GMT 时区格式化当前时间吗?[复制] 2017-12-26 11:35:07 +0800 CST
  • Martin Hope
    AllisonC 如何复制目录并在同一命令中重命名它? 2017-12-22 05:28:06 +0800 CST
  • Martin Hope
    Steve “root”用户的文件权限如何工作? 2017-12-22 02:46:01 +0800 CST
  • Martin Hope
    Bagas Sanjaya 为什么 Linux 使用 LF 作为换行符? 2017-12-20 05:48:21 +0800 CST
  • Martin Hope
    Cbhihe 将默认编辑器更改为 vim for _ sudo systemctl edit [unit-file] _ 2017-12-03 10:11:38 +0800 CST
  • Martin Hope
    showkey 如何下载软件包而不是使用 apt-get 命令安装它? 2017-12-03 02:15:02 +0800 CST
  • Martin Hope
    youxiao 为什么目录 /home、/usr、/var 等都具有相同的 inode 编号 (2)? 2017-12-02 05:33:41 +0800 CST
  • Martin Hope
    user223600 gpg —list-keys 命令在将私钥导入全新安装后输出 uid [未知] 2017-11-26 18:26:02 +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