符合POSIX标准的shell中的数组

时间:2016-02-13 22:14:54

标签: arrays bash posix dash-shell

根据this reference sheet on hyperpolyglot.org,可以使用以下语法来设置数组。

i=(1 2 3)

但是我在 dash 上遇到错误,这是Ubuntu上/bin/sh的默认值,应该符合POSIX标准。

# Trying the syntax with dash in my terminal
> dash -i
$ i=(1 2 3)
dash: 1: Syntax error: "(" unexpected
$ exit

# Working fine with bash
> bash -i
$ i=(1 2 3)
$ echo ${i[@]}
1 2 3
$ exit

参考表是否误导或错误?
如果是,那么定义数组或列表并且符合POSIX的正确方法是什么?

3 个答案:

答案 0 :(得分:7)

Posix不指定数组,因此如果限制为Posix shell功能,则不能使用数组。

我担心你的引用是错误的。可悲的是,并非您在互联网上找到的所有内容都是正确的。

答案 1 :(得分:6)

正如rici所说,破折号没有阵列支持。但是,如果你要做的是编写一个循环,那么有一些解决方法。

For循环不会执行数组,但您可以使用while循环+ read builtin进行拆分。由于破译读取内置也不支持分隔符,因此您也必须解决这个问题。

以下是一个示例脚本:

myArray="a b c d"

echo "$myArray" | tr ' ' '\n' | while read item; do
  # use '$item'
  echo $item
done

对此有一些更深入的解释:

  • “tr'''\ n'”将允许您在其中进行单字符替换 你删除空格&添加换行符 - 这是默认的分隔符 阅读内置。

  • “read”将在检测到stdin时以失败的退出代码退出 已关闭 - 这将是您的输入完全 处理。

  • 由于echo在输入后会打印一个额外的换行符,这样就可以了 处理数组中的最后一个“元素”。

这相当于bash代码:

myArray=(a b c d)

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

如果你想要检索第n个元素(假设为了示例的目的,则为第2个):

myArray="a b c d"

echo $myArray | cut -d\  -f2 # change -f2 to -fn

答案 2 :(得分:0)

的确,POSIX sh外壳没有与bash和其他外壳具有相同意义的命名数组,但是有一个{{ 1}}壳(以及sh和其他壳)都可以使用,这就是位置参数的列表。

此列表通常包含传递给当前脚本或shell函数的参数,但是您可以使用bash内置命令来设置其值:

set

在上面的脚本中,位置参数#!/bin/sh set -- this is "a list" of "several strings" $1,...被设置为所示的五个字符串。 $2用于确保您不会意外地设置shell选项(--命令也可以这样做)。但是,只有第一个参数以set开头时,这才是问题。

例如遍历这些字符串,您可以使用

-

或更短的

for string in "$@"; do
    printf 'Got the string "%s"\n' "$string"
done

或者只是

for string do
    printf 'Got the string "%s"\n' "$string"
done

printf 'Got the string "%s"\n' "$@" 对于将全局扩展为路径名列表也很有用:

set

#!/bin/sh set -- "$HOME"/*/ # "visible directory" below really means "visible directory, or visible # symbolic link to a directory". if [ ! -d "$1" ]; then echo 'You do not have any visible directories in your home directory' else printf 'There are %d visible directories in your home directory\n' "$#" echo 'These are:' printf '\t%s\n' "$@" fi 内置命令可用于从列表中移出第一个位置参数。

shift