在排除数组中跳过bash中的项目

时间:2014-09-09 17:01:02

标签: bash

我有一个循环数据库名称的脚本,如果当前数据库的名称在我的排除数组中,我想跳过它。我将如何在bash中实现这一目标?

excluded_databases=("template1" "template0")

for database in $databases
do
  if ...; then
    # perform something on the database...
  fi
done

3 个答案:

答案 0 :(得分:2)

您可以依次测试每个名称,但最好在一次操作中过滤列表。 (以下假设$databases中没有名称包含空格,在for循环中隐含空格。

for database in $(printf %s\\n $databases |
                  grep -Fvx "${excluded_databases[@]/#/-e}"); do
  # something
done

习语的解释:

  1. printf %s\\n ...在一行上打印每个参数。

  2. grep -Fvx搜索整行(-F)的完全匹配(-x)并反转匹配结果(-v)。

  3. "${array[@]/#/-e}"-e添加到数组array的每个元素,这在您需要将数组的每个元素作为(重复的)命令行提供时非常有用实用程序的选项。在这种情况下,实用程序为grep-e标志用于提供匹配模式。

  4. 我过去曾因printf %s\\n而受到批评 - 有些人更喜欢printf '%s\n' - 但我发现第一个更容易打字。 YMMV。


    作为评论,似乎最好使$databases成为数组以及$excluded_databases,这将允许包含空格的名称。 printf | grep解决方案仍然不允许名称中的换行符;解决这个问题很复杂。如果您要进行更改,则只需将printf更改为printf %s\\n "${databases[@]}"

答案 1 :(得分:1)

您可以使用此条件检查数组中是否存在元素:

if [[ "${excluded_databases[@]/$database}" == "${excluded_databases[@]}" ]]

使用case的另一个选项:

case "${excluded_databases[@]}" in *"$database"*) echo "found in array" ;; esac

答案 2 :(得分:1)

如果您使用的是bash 4或更高版本,那么使用关联数组会对您有帮助。

declare -A excluded_databases=(["template1"]=1 ["template0"]=1)

for database in $databases
do
    if [ -z "${excluded_databases[$database]}" ]; then
        continue
    fi
    # ... do something with $database
done