如何将bash样式的数组移植到ash?


13

前段时间,我编写了一个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种服务在阵列中,我想使这种过渡尽可能轻松,整洁。一直在使用bashisms。现在,我正忙于使脚本更具可移植性的任务。

出于可移植性的原因,最好有一个纯粹的ash解决方案。但是,由于我拥有足够强大的能力busybox,因此我可能会牺牲一些可移植性。只有在可读性得到很大提高的情况下,因为“干净”脚本也是一个度量标准。

什么是便携式清洁在这种情况下的解决方案?

Answers:


8

在将数组放入bashksh和其他外壳程序之前,通常的方法是选择一个不在任何元素中的定界符(或不常见的定界符,以最小化所需的转义),并遍历包含所有元素的字符串,用该分隔符分隔。空格通常是最方便的定界符选择,因为默认情况下外壳程序已将空格分隔为“单词”(如果希望将IFS拆分为其他内容,则可以设置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应该不是在这里,因为我们的双引号外壳将它拆分成“单词”。


3

ash没有数组。唯一接近的是位置参数,因此您可以

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

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

3

如果您只需要参考一次服务列表,则可以使用here-doc:

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

请注意,服务名称不应在列表中加引号(尽管"$service"可能应加引号,除非您有充分的理由不加引号)。如果您希望缩进服务名称,请使用<<-代替,<<然后在标签中缩进名称:

while IFS= read -r service
do
   START "$service"
done <<- END
        service1.service
        service2.service
        service3.service
END
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.