如何将bash风格的数组移植到ash?

如何将bash风格的数组移植到ash?

前段时间我编写了一个 bash 脚本,现在应该能够在ash.

其中bash就像:

services=( "service1.service"
           "service2.service"                                       
           "service3.service" )  

for service in "${services[@]}"
do
   START $service                   
done

START()
{
   echo "Starting "$1
   systemctl start $1
}

实际上,阵列中有大约 40 个服务,我希望使这种过渡尽可能轻松、干净。一直在用bash主义。现在我面临着使脚本更可移植的任务。

出于可移植性的原因,最好有一个纯粹的ash解决方案。但由于我有一个相当强大的设备busybox可供使用,我可能会牺牲一些便携性。仅当可读性大大提高时,因为“干净”的脚本也是一个指标。

会是什么便携的干净的这种情况下的解决方案?

答案1

在数组出现在 、 和其他 shell 中之前bashksh通常的方法是选择一个不在任何元素中的分隔符(或者是不常见的分隔符,以最大限度地减少任何所需的转义),并迭代包含所有元素的字符串,由该分隔符分隔。空格通常是最方便的分隔符选择,因为 shell 默认情况下已经按空格分割“单词”(如果您希望它在不同的内容上分割,可以设置 IFS)。

例如:

# backslash-escape any non-delimiter whitespace and all other characters that
# have special meaning to the shell, e.g. globs, parenthesis, ampersands, etc.
services='service1.service service2.service service3.service'

for s in $services ; do  # NOTE: do not double-quote $services here.
  START "$s"
done

$services应该不是在这里用双引号引起来,因为我们shell 将其拆分为“单词”。

答案2

ash 没有数组。唯一接近的是位置参数,所以你可以这样做

set -- "service1.service" \
       "service2.service" \
       "service3.service"

for service in "$@"
do
   START $service
done

答案3

如果您只需要引用服务列表一次,则可以使用此处文档:

while IFS= read -r service
do
   START "$service"
done << END
service1.service
service2.service
service3.service
END

请注意,服务名称不应在列表中加引号(尽管"$service"可能应该加引号,除非您有充分的理由不这样做)。如果您希望服务名称缩进,请使用<<-not<<并使用制表符缩进名称:

while IFS= read -r service
do
   START "$service"
done <<- END
        service1.service
        service2.service
        service3.service
END

答案4

您可以通过创建带有fix前缀的变量来模拟数组

示例1:

#!/bin/ash

# simulate array variables
comment_wifi='wifi-text'
comment_status='some-state'
comment_0=1234
comment_1=7878
comment_2=9999

for v in wifi status $(seq 0 2)
do
 # construct variable and get its value
 eval value="\$comment_${v}"

 echo "comment_${v}: ${value}"
done

输出:

comment_wifi: wifi-text
comment_status: some-state
comment_0: 1234
comment_1: 7878
comment_2: 9999

示例2:

#!/bin/ash

# fill create and variables 
for v in wifi status $(seq 0 2)
do
  # example value
  a_value="$(cat /proc/uptime)"

  # construct variable and assign value
  eval comment_${v}="\$a_value";
done

# output
for v in wifi status $(seq 0 2)
do
 # construct variable and get its value
 eval value="\$comment_${v}";

 echo "comment_${v}: ${value}"
done

输出:

comment_wifi: 5954.23 22504.11
comment_status: 5954.24 22504.12
comment_0: 5954.24 22504.14
comment_1: 5954.25 22504.16
comment_2: 5954.25 22504.17

相关内容