循环访问bash中的字符串数组?

 2019-05-06 

Loop through an array of strings in Bash?

我想写一个循环15个字符串的脚本(可能是数组?)有可能吗?

类似:

1
2
3
4
for databaseName in listOfNames
then
  # Do something
end

您可以这样使用它:

1
2
3
4
5
6
7
8
9
10
11
## declare an array variable
declare -a arr=("element1""element2""element3")

## now loop through the above array
for i in"${arr[@]}"
do
   echo"$i"
   # or do whatever with individual element of the array
done

# You can access them using echo"${arr[0]}","${arr[1]}" also

也适用于多行数组声明

1
2
3
4
declare -a arr=("element1"
               "element2""element3"
               "element4"
                )


当然,这是可能的。

1
2
3
for databaseName in a b c d e f; do
  # do something like: echo $databaseName
done

有关详细信息,请参阅bash循环。


这些答案都不包括计数器…

1
2
3
4
5
6
7
8
9
10
11
12
#!/bin/bash
## declare an array variable
declare -a array=("one""two""three")

# get length of an array
arraylength=${#array[@]}

# use for loop to read all values and indexes
for (( i=1; i<${arraylength}+1; i++ ));
do
  echo $i" /" ${arraylength}" :" ${array[$i-1]}
done

输出:

1
2
3
1  /  3  :  one
2  /  3  :  two
3  /  3  :  three


以4ndrew的回答同样的精神:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
listOfNames="RA
RB
R C
RD"


# To allow for other whitespace in the string:
# 1. add double quotes around the list variable, or
# 2. see the IFS note (under 'Side Notes')

for databaseName in"$listOfNames"   #  <-- Note: Added"" quotes.
do
  echo"$databaseName"  # (i.e. do action / processing of $databaseName here...)
done

# Outputs
# RA
# RB
# R C
# RD

b.名称中无空格:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
listOfNames="RA
RB
R C
RD"


for databaseName in $listOfNames  # Note: No quotes
do
  echo"$databaseName"  # (i.e. do action / processing of $databaseName here...)
done

# Outputs
# RA
# RB
# R
# C
# RD

笔记

  • 在第二个示例中,使用listOfNames="RA RB R C RD"具有相同的输出。
  • 引入数据的其他方法包括:

    • stdin(如下所列)
    • 变量,
    • 一个数组(接受的答案),
    • 文件…

    从STDIN读取

    1
    2
    3
    4
    5
    # line delimited (each databaseName is stored on a line)
    while read databaseName
    do
      echo"$databaseName"  # i.e. do action / processing of $databaseName here...
    done # <<< or_another_input_method_here
  • bash ifs"字段分隔符到行"[1]分隔符可以在脚本中指定,以允许其他空白(即IFS='
    '
    或macos IFS='
    '
    )
  • 我也喜欢这个被接受的答案:)——我把这些片段作为其他有帮助的方式来回答这个问题。
  • 其中脚本文件顶部的#!/bin/bash表示执行环境。
  • 我花了几个月的时间才弄明白如何简单地编写代码:)
  • 其他来源(读取循环时)


    是的

    1
    2
    3
    4
    for Item in Item1 Item2 Item3 Item4 ;
      do
        echo $Item
      done

    输出:

    1
    2
    3
    4
    Item1
    Item2
    Item3
    Item4

    在多行上

    1
    2
    3
    4
    5
    6
    7
    for Item in Item1 \
                Item2 \
                Item3 \
                Item4
      do
        echo $Item
      done

    输出:

    1
    2
    3
    4
    Item1
    Item2
    Item3
    Item4

    简单列表变量

    1
    List=( Item1 Item2 Item3 )

    1
    2
    3
    4
    5
    List=(
          Item1
          Item2
          Item3
         )

    显示列表变量:

    1
    echo ${List[*]}

    输出:

    1
    Item1 Item2 Item3

    循环浏览列表:

    1
    2
    3
    4
    for Item in ${List[*]}
      do
        echo $Item
      done

    输出:

    1
    2
    3
    Item1
    Item2
    Item3

    创建函数以浏览列表:

    1
    2
    3
    4
    5
    6
    7
    Loop(){
      for item in ${*} ;
        do
          echo ${item}
        done
    }
    Loop ${List[*]}

    保留空格;单引号或双引号列表项和双引号列表扩展:

    1
    2
    3
    4
    5
    6
    7
    8
    List=(' Item 1 '
          ' Item 2'
          ' Item 3'
         )
    for item in"${List[@]}";
      do
        echo"$item"
      done

    输出:

    1
    2
    3
     Item 1
     Item 2
     Item 3

    使用declare关键字(命令)创建列表,该列表在技术上称为数组:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    declare -a List=(
                    "element 1"
                    "element 2"
                    "element 3"
                    )
    for entry in"${List[@]}"
       do
         echo"$entry"
       done

    输出:

    1
    2
    3
    element 1
    element 2
    element 3

    创建关联数组。字典:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    declare -A continent

    continent[Vietnam]=Asia
    continent[France]=Europe
    continent[Argentina]=America

    for item in"${!continent[@]}";
      do
        printf"$item is in ${continent[$item]}
    "

      done

    输出:

    1
    2
    3
     Argentina is in America
     Vietnam is in Asia
     France is in Europe

    cvs变量或文件在列表中。将内部字段分隔符从空格更改为所需内容。在下面的示例中,它改为逗号

    1
    2
    3
    4
    5
    6
    7
    8
    List="Item 1,Item 2,Item 3"
    Backup_of_internal_field_separator=$IFS
    IFS=,
    for item in $List;
      do
        echo $item
      done
    IFS=$Backup_of_internal_field_separator

    输出:

    1
    2
    3
    Item 1
    Item 2
    Item 3

    如果需要编号:

    1
    `

    这叫做倒勾。把命令放回刻度内。

    1
    `commend`

    它在键盘上数字1的旁边,或者在tab键的上方。在标准的美式英语键盘上。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    List=()
    Start_count=0
    Step_count=0.1
    Stop_count=1
    for Item in `seq $Start_count $Step_count $Stop_count`
        do
           List+=(Item_$Item)
        done
    for Item in ${List[*]}
        do
            echo $Item
        done

    输出为:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    Item_0.0
    Item_0.1
    Item_0.2
    Item_0.3
    Item_0.4
    Item_0.5
    Item_0.6
    Item_0.7
    Item_0.8
    Item_0.9
    Item_1.0

    更熟悉巴什的行为:

    在文件中创建列表

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    cat <<EOF> List_entries.txt
    Item1
    Item 2
    'Item 3'
    "Item 4"
    Item 7 : *
    "Item 6 : *"
    "Item 6 : *"
    Item 8 : $PWD
    'Item 8 : $PWD'
    "Item 9 : $PWD"
    EOF

    将列表文件读入列表并显示

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    List=$(cat List_entries.txt)
    echo $List
    echo '$List'
    echo"$List"
    echo ${List[*]}
    echo '${List[*]}'
    echo"${List[*]}"
    echo ${List[@]}
    echo '${List[@]}'
    echo"${List[@]}"

    bash命令行参考手册:特定字符或单词对shell的特殊意义。


    您可以使用${arrayName[@]}的语法。

    1
    2
    3
    4
    5
    6
    7
    #!/bin/bash
    # declare an array called files, that contains 3 values
    files=("/etc/passwd""/etc/group""/etc/hosts" )
    for i in"${files[@]}"
    do
        echo"$i"
    done


    这也很容易理解:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    FilePath=(
       "/tmp/path1/"    #FilePath[0]
       "/tmp/path2/"    #FilePath[1]
    )

    #Loop
    for Path in"${FilePath[@]}"
    do
        echo"$Path"
    done


    令人惊讶的是,还没有人发布这个消息——如果在循环遍历数组时需要元素的索引,可以这样做:

    1
    2
    3
    4
    5
    6
    arr=(foo bar baz)

    for i in ${!arr[@]}
    do
        echo $i"${arr[i]}"
    done

    输出:

    1
    2
    3
    0 foo
    1 bar
    2 baz

    我发现这比"传统"的循环样式(for (( i=0; i<${#arr[@]}; i++ )))要优雅得多。

    (${!arr[@]}$i不需要报价,因为它们只是数字;有些人会建议无论如何报价,但这只是个人偏好。)


    脚本或函数的隐式数组:

    除了Anubhava的正确答案:如果循环的基本语法是:

    1
    for var in"${arr[@]}" ;do ...$var... ;done

    在bash中有一个特殊情况:

    在运行脚本或函数时,在命令行传递的参数将被分配给$@数组变量,您可以通过$1$2$3等访问。

    可通过以下方式填充(用于测试)

    1
    set -- arg1 arg2 arg3 ...

    可以简单地编写此数组的循环:

    1
    2
    3
    for item ;do
        echo"This is item: $item."
      done

    注意,保留的工作in不存在,也没有数组名!

    Sample:

    1
    2
    3
    4
    5
    6
    7
    8
    set -- arg1 arg2 arg3 ...
    for item ;do
        echo"This is item: $item."
      done
    This is item: arg1.
    This is item: arg2.
    This is item: arg3.
    This is item: ....

    注意这和

    1
    2
    3
    for item in"$@";do
        echo"This is item: $item."
      done

    然后进入脚本:

    1
    2
    3
    4
    5
    6
    #!/bin/bash

    for item ;do
        printf"Doing something with '%s'.
    "
    "$item"
      done

    把它保存在脚本myscript.shchmod +x myscript.sh中,然后

    1
    2
    3
    4
    5
    ./myscript.sh arg1 arg2 arg3 ...
    Doing something with 'arg1'.
    Doing something with 'arg2'.
    Doing something with 'arg3'.
    Doing something with '...'.

    功能相同:

    1
    myfunc() { for item;do cat <<<"Working about '$item'."; done ; }

    然后

    1
    2
    3
    4
    myfunc item1 tiem2 time3
    Working about 'item1'.
    Working about 'tiem2'.
    Working about 'time3'.

    declare数组不适用于korn shell。对Korn Shell使用以下示例:

    1
    2
    3
    4
    5
    6
    7
    8
    promote_sla_chk_lst="cdi xlob"

    set -A promote_arry $promote_sla_chk_lst

    for i in ${promote_arry[*]};
        do
                echo $i
        done


    1
    2
    3
    4
    5
    listOfNames="db_one db_two db_three"
    for databaseName in $listOfNames
    do
      echo $databaseName
    done

    或者只是

    1
    2
    3
    4
    for databaseName in db_one db_two db_three
    do
      echo $databaseName
    done


    简单方法:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    arr=("sharlock" "bomkesh" "feluda" )  ##declare array

    len=${#arr[*]}  # it returns the array length

    #iterate with while loop
    i=0
    while [ $i -lt $len ]
    do
        echo ${arr[$i]}
        i=$((i+1))
    done


    #iterate with for loop
    for i in $arr
    do
      echo $i
    done

    #iterate with splice
     echo ${arr[@]:0:3}

    如果您使用的是Korn Shell,则会出现"set-a databasename",否则会出现"declare-a databasename"。

    要在所有shell上编写脚本,

    1
    2
    3
    4
    5
    6
    7
    8
     set -A databaseName=("db1""db2" ....) ||
            declare -a databaseName=("db1""db2" ....)
    # now loop
    for dbname in"${arr[@]}"
    do
       echo"$dbname"  # or whatever

    done

    它应该适用于所有外壳。


    这类似于用户253809的回答,但每个文件将作为单独的命令执行。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    #!/bin/bash
    names="RA
    RB
    R C
    RD"


    while read -r line; do
        echo line:"$line"
    done <<<"$names"

    试试这个。它正在工作和测试。

    1
    2
    3
    4
    5
    6
    for k in"${array[@]}"
    do
        echo $k
    done

    # For accessing with the echo command: echo ${array[0]}, ${array[1]}


    单线循环,

    1
    2
     declare -a listOfNames=('db_a' 'db_b' 'db_c')
     for databaseName in ${listOfNames[@]}; do echo $databaseName; done;

    你会得到这样的输出,

    1
    2
    3
    db_a
    db_b
    db_c


    每个bash脚本/会话的可能第一行:

    1
    2
    say() { for line in"${@}" ; do printf"%s
    "
    "${line}" ; done ; }

    使用:

    1
    2
    3
    4
    $ aa=( 7 -4 -e ) ; say"${aa[@]}"
    7
    -4
    -e

    可以考虑:echo-e解释为此处的选项。


    我循环查看我的项目数组,以获取git pull更新:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    #!/bin/sh
    projects="
    web
    ios
    android
    "

    for project in $projects do
        cd  $HOME/develop/$project && git pull
    end