![如何将bash风格的数组移植到ash?](https://linux22.com/image/115729/%E5%A6%82%E4%BD%95%E5%B0%86bash%E9%A3%8E%E6%A0%BC%E7%9A%84%E6%95%B0%E7%BB%84%E7%A7%BB%E6%A4%8D%E5%88%B0ash%EF%BC%9F.png)
前段时间我编写了一个 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 中之前bash
,ksh
通常的方法是选择一个不在任何元素中的分隔符(或者是不常见的分隔符,以最大限度地减少任何所需的转义),并迭代包含所有元素的字符串,由该分隔符分隔。空格通常是最方便的分隔符选择,因为 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