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 / 问题 / 493729
Accepted
mja
mja
Asked: 2019-01-11 06:13:31 +0800 CST2019-01-11 06:13:31 +0800 CST 2019-01-11 06:13:31 +0800 CST

支持 `local` 关键字定义局部变量的 shell 列表

  • 772

我知道 Bash 和 Zsh 支持local变量,但是有些系统只有 POSIX 兼容的 shell。并且local在 POSIX shell 中未定义。

所以我想问一下哪些shell支持local定义局部变量的关键字?

编辑:关于外壳我的意思是默认/bin/sh外壳。

shell-script shell
  • 2 2 个回答
  • 5106 Views

2 个回答

  • Voted
  1. Best Answer
    Stéphane Chazelas
    2019-01-11T07:29:20+08:002019-01-11T07:29:20+08:00

    不是支持不支持那么简单local。语法有很多变化,以及在具有一种或其他局部范围的 shell 之间是如何完成的。

    这就是为什么很难提出一个所有人都同意的标准。有关这方面的 POSIX 工作,请参见http://austingroupbugs.net/bug_view_page.php?bug_id=767。

    80 年代初,ksh 中首先添加了本地范围。

    在函数中声明局部变量的语法是typeset:

    function f {
      typeset var=value
      set -o noglob # also local to the function
      ...
    }
    

    (函数支持后来被添加到 Bourne shell 中,但是使用了不同的语法 ( f() command) 并且后来也添加了对该函数的支持ksh;Bourne shell 从来没有本地范围(当然通过子 shell 除外))

    local内置 AFAIK 于 1989 年首次添加到 Almquist shell(用于 BSD、dash、busybox sh)中,但其工作方式ksh与typeset. ash导数不支持typeset作为 的别名local,但您始终可以手动定义一个。

    bash 和 zsh分别在 1989 年和 1991 年添加了typeset别名。local

    ksh88 添加local为typeset大约 1990 年和 1994 年 pdksh 及其衍生产品的未记录别名。 posh(基于pdksh)删除typeset(为了严格遵守需要 Debian 政策local,但不是typeset)。

    POSIX 最初反对指定typeset它是动态范围。所以 ksh93(David Korn 在 1993 年对 ksh 的重写)改为使用静态作用域。同样在 ksh93 中,与 ksh88 不同,本地范围仅适用于使用语法 ( ) 声明的函数ksh,function f {...}而不是 Bourne 语法 ( f() {...}),并且local别名已被删除。

    然而,来自 AT&T 的 ksh93v- beta 和最终版本可以使用实验性的“bash”模式(实际上默认启用)进行编译,该模式local在typeset被ksh93调用为bash. local与typeset这种情况的不同之处在于它只能从函数内调用。该bash模式将在 ksh2020 中默认禁用,尽管localdeclaretypeset/别名将保留,即使未编译 bash 模式(尽管仍具有静态范围)。

    yash(写得很久以后),有typeset(à la ksh88),但自 2.48 版(2018 年 12 月)以来,它只是local作为它的别名。

    @Schily(遗憾的是,他于 2021 年去世)曾经维护一个 Bourne shell 后代,该后代最近主要符合 POSIX 标准,bosh自 2016-07-06 版本起支持本地作用​​域(带有local,类似于ash)。

    因此,今天具有某种形式的变量局部范围的 Bourne 类 shell 是:

    • ksh,所有实现及其衍生产品(ksh88、ksh93、pdksh 和衍生产品,如 posh、mksh、OpenBSD sh)。
    • ash 及其所有衍生产品(NetBSD sh、FreeBSD sh、dash、busybox sh)
    • 重击
    • zsh
    • 雅什
    • 波什

    就sh不同系统而言,请注意,有些系统(大多数)存在 POSIX sh,/bin而其他系统则不存在(例如 Solaris /usr/xpg4/bin)。对于sh在各种系统上的实施,我们有:

    • ksh88:大多数 SysV 派生的商业 Unices(AIX、HP/UX、Solaris¹...)
    • bash:大多数 GNU/Linux 系统、Cygwin、macOS
    • ash:默认情况下,在 Debian 和大多数衍生产品(包括 Ubuntu、Linux/Mint)上,管理员可以将其更改为 bash 或 mksh。NetBSD、FreeBSD 和它们的一些衍生产品(不是 macOS)。
    • busybox sh:很多(如果不是大多数)嵌入式 Linux 系统
    • pdksh 或衍生产品:OpenBSD、MirBSD、Android

    现在,它们的不同之处在于:

    • typeset(ksh,pdksh,bash,zsh,yash)与local(ksh88,pdksh,bash,zsh,ash,yash 2.48+)。
    • 支持的选项列表。
    • 静态(ksh93,在function f {...}函数中)与动态范围(所有其他外壳)。例如,无论是function f { typeset v=1; g; echo "$v"; }; function g { v=2; }; f输出1还是2. 另请参阅该export属性如何影响ksh93.
    • 是否local/typeset只是将变量设为局部变量(ash, bosh),还是创建变量的新实例(其他 shell)。例如,是否v=1; f() { local v; echo "${v:-empty}"; }; f输出1或empty(另请参阅localvar_inheritbash 5.0 及更高版本中的选项)。
    • 对于那些创建新变量的变量,新变量是否继承了属性(如export)和/或类型,以及哪些来自父范围内的变量。例如,是否export V=1; f() { local V=2; printenv V; }; f打印1,2或者什么都没有。
    • 该新变量是否具有初始值(空、0、空列表,取决于类型zsh)或最初未设置。
    • 无论unset V是在局部范围内的变量上留下变量unset,还是只剥离一层范围(在某些情况下,,)mksh。例如,是否有输出(另请参阅bash 5.0 及更高版本中的选项)yashbashv=1; f() { local v=2; unset v; echo "$v"; }1localvar_unset
    • 比如 for export,无论是关键字还是仅仅是内置的或两者兼而有之,以及在什么条件下它被视为关键字。
    • 比如 for export,参数是被解析为普通命令参数还是赋值(以及在什么条件下)。
    • 是否可以在父范围内声明一个只读变量。
    • 与v=value myfunctionwheremyfunction本身的交互是否声明v为本地。

    这就是我刚才在想的那些。查看上面的 austin group 错误以获取更多详细信息。

    至于 shell选项的本地范围(与variables相对),支持它的 shell 是:

    • ksh88(使用两种函数定义语法):默认完成,我不知道有什么方法可以禁用它。
    • ash(自 1989 年以来):与local -. 它使$-参数(存储选项列表)本地化。
    • ksh93: 现在只为function f {...}函数做。
    • zsh(自 1995 年以来)。与setopt localoptions. 还emulate -L可以将仿真模式(及其选项集)设置为函数的本地。
    • bash(自 2016 年起)与local -类似ash,但仅适用于由 管理的选项set,而不是由 管理的选项shopt。

    ¹ shSolaris 上的 POSIX 是/usr/xpg4/bin/sh(尽管它有许多一致性错误,包括函数的本地选项)。/bin/sh直到 Solaris 10 是 Bourne shell(所以没有本地范围),并且由于 Solaris 11 是 ksh93

    • 32
  2. glenn jackman
    2019-01-11T16:05:06+08:002019-01-11T16:05:06+08:00

    为了跟进 Stéphane 的回答中的提示,使用 subshel​​ls 可以获得本地效果。我无法访问真正的 POSIX shell,但这在busybox 中有效——用括号而不是大括号ash声明你的函数。这会强制函数在子 shell 中运行。(){}

    func() (
        echo "in func, before declaring: x=$x"
        x=10
        echo "in func, after declaring: x=$x"
    )
    
    x=5
    echo "before func: x=$x"
    func
    echo "after func: x=$x"
    

    输出

    before func: x=5
    in func, before declaring: x=5
    in func, after declaring: x=10
    after func: x=5
    

    这表明该函数可以访问全局变量,并且在函数中设置变量不会改变全局变量。当我想更改$IFS或cd转到不同的目录时,我有时会使用这种技术,但我不希望这些操作影响程序的其余部分。

    • 7

相关问题

  • 打印文件行及其长度的脚本[关闭]

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

  • 按分隔符拆分并连接字符串问题

  • 如何将带有〜的路径保存到变量中?

  • MySQL Select with function IN () with bash array

Sidebar

Stats

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

    模块 i915 可能缺少固件 /lib/firmware/i915/*

    • 3 个回答
  • Marko Smith

    无法获取 jessie backports 存储库

    • 4 个回答
  • Marko Smith

    如何将 GPG 私钥和公钥导出到文件

    • 4 个回答
  • Marko Smith

    我们如何运行存储在变量中的命令?

    • 5 个回答
  • Marko Smith

    如何配置 systemd-resolved 和 systemd-networkd 以使用本地 DNS 服务器来解析本地域和远程 DNS 服务器来解析远程域?

    • 3 个回答
  • Marko Smith

    dist-upgrade 后 Kali Linux 中的 apt-get update 错误 [重复]

    • 2 个回答
  • Marko Smith

    如何从 systemctl 服务日志中查看最新的 x 行

    • 5 个回答
  • Marko Smith

    Nano - 跳转到文件末尾

    • 8 个回答
  • Marko Smith

    grub 错误:你需要先加载内核

    • 4 个回答
  • Marko Smith

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

    • 7 个回答
  • Martin Hope
    user12345 无法获取 jessie backports 存储库 2019-03-27 04:39:28 +0800 CST
  • Martin Hope
    Carl 为什么大多数 systemd 示例都包含 WantedBy=multi-user.target? 2019-03-15 11:49:25 +0800 CST
  • Martin Hope
    rocky 如何将 GPG 私钥和公钥导出到文件 2018-11-16 05:36:15 +0800 CST
  • Martin Hope
    Evan Carroll systemctl 状态显示:“状态:降级” 2018-06-03 18:48:17 +0800 CST
  • Martin Hope
    Tim 我们如何运行存储在变量中的命令? 2018-05-21 04:46:29 +0800 CST
  • Martin Hope
    Ankur S 为什么 /dev/null 是一个文件?为什么它的功能不作为一个简单的程序来实现? 2018-04-17 07:28:04 +0800 CST
  • Martin Hope
    user3191334 如何从 systemctl 服务日志中查看最新的 x 行 2018-02-07 00:14:16 +0800 CST
  • Martin Hope
    Marko Pacak Nano - 跳转到文件末尾 2018-02-01 01:53:03 +0800 CST
  • Martin Hope
    Kidburla 为什么真假这么大? 2018-01-26 12:14:47 +0800 CST
  • Martin Hope
    Christos Baziotis 在一个巨大的(70GB)、一行、文本文件中替换字符串 2017-12-30 06:58:33 +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