Bash将以空格分隔的字符串拆分为可变数量的子字符串

时间:2014-11-11 23:47:46

标签: string bash

假设我的bash脚本中有两个以空格分隔的字符串,它们是

permitted_hosts="node1 node2 node3"

runs_list="run1 run2 run3 run4 run5"

这些分别代表允许的主机列表和要执行的运行列表。因此,我需要在$runs_list中的一个主机上的$permitted_hosts中运行每次运行。

我想要做的是将$runs_list划分为$N子字符串,其中$N$permitted_hosts中的元素数量以及每个{{1}子字符串映射到$N中的其他元素。

如果这令人困惑,那么请考虑这个具体的解决方案。对于上面$permitted_hosts$permitted_hosts的确切给定值,以下bash脚本会检查当前主机,如果当前主机位于$runs_list,则会在{{1}中启动运行与当前主机关联的。当然,此脚本不使用变量$permitted_hosts$runs_list,但它可以实现给定示例的预期效果。我真正要做的是修改下面的代码,以便我可以修改变量$permitted_hosts$runs_list的值,它将正常工作。

$permitted_hosts

1 个答案:

答案 0 :(得分:1)

所以,首先 - 你应该使用数组来代替空格分隔的字符串:

permitted_hosts=(node1 node2 node3)
runs_list=(run1 run2 run3 run4 run5)

如果你必须从空格分隔的字符串开始,你至少可以将它们转换为数组:

permitted_hosts=($permitted_hosts_str)
runs_list=($runs_list_str)

那个偏僻。 。 。基本上你有两个步骤:(1)将主机名转换为一个整数,表示它在permitted_hosts中的位置:

hostname="$(hostname)"
num_hosts="${#permitted_hosts[@]}"      # for convenience

host_index=0
while true ; do
    if [[ "${permitted_hosts[host_index]}" = "$hostname" ]] ; then
        break
    fi
    (( ++host_index ))
    if (( host_index > num_hosts )) ; then
        printf 'ERROR: Invoked on invalid host ('%s')! Aborting.\n' "$hostname" >&2
        exit 1
    fi
done
# host_index is now an integer index into permitted_hosts

和(2)将此整数转换为runs_list的适当子集:

num_runs="${#runs_list[@]}"      # for convenience
for (( run_index = host_index ; run_index < num_runs ; run_index += num_hosts )) ; do
    ./launch "${runs_list[run_index]}"
done

因此,例如,如果你有 H 主机,那么主机#0将启动运行#0,运行# H ,运行#2 H < / em>等;主机#1将启动运行#1,运行# H +1,运行#2 H +1等;等等。