Loop through an array of strings in Bash?

2018-12-31 13:56发布

问题:

I want to write a script that loops through 15 strings (array possibly?) Is that possible?

Something like:

for databaseName in listOfNames
then
  # Do something
end

回答1:

You can use it like this:

## 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

Also works for multi-line array declaration

declare -a arr=(\"element1\" 
                \"element2\" \"element3\"
                \"element4\"
                )


回答2:

That is possible, of course.

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

See Bash Loops for, while and until for details.



回答3:

None of those answers include a counter...

#!/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

Output:

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


回答4:

In the same spirit as 4ndrew\'s answer:

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. No whitespace in the names:

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

Notes

  1. In the second example, using listOfNames=\"RA RB R C RD\" has the same output.

Other ways to bring in data include:

  • stdin (listed below),
  • variables,
  • an array (the accepted answer),
  • a file...

Read from stdin

# 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
  1. the bash IFS \"field separator to line\" [1] delimiter can be specified in the script to allow other whitespace (i.e. IFS=\'\\n\', or for MacOS IFS=\'\\r\')
  2. I like the accepted answer also :) -- I\'ve include these snippets as other helpful ways that also answer the question.
  3. Including #!/bin/bash at the top of the script file indicates the execution environment.
  4. It took me months to figure out how to code this simply :)

Other Sources (while read loop)



回答5:

Yes

for Item in Item1 Item2 Item3 Item4 ;
  do
    echo $Item
  done

Output :

Item1
Item2
Item3
Item4

Over multiple lines

for Item in Item1 \\
            Item2 \\
            Item3 \\
            Item4
  do
    echo $Item
  done

Output :

Item1
Item2
Item3
Item4


Simple list variable

List=( Item1 Item2 Item3 )

or

List=(
      Item1 
      Item2 
      Item3
     )

Display the list variable :

echo ${List[*]}

Out put :

Item1 Item2 Item3

Loop through the list:

for Item in ${List[*]} 
  do
    echo $Item 
  done

Out put :

Item1
Item2
Item3

Create a function to go through a list:

Loop(){
  for item in ${*} ; 
    do 
      echo ${item} 
    done
}
Loop ${List[*]}

To preserve spaces ; single or double quote list entries and double quote list expansions :

List=(\' Item 1 \'
      \' Item 2\' 
      \' Item 3\'
     )
for item in \"${List[@]}\"; 
  do 
    echo \"$item\"
  done 

Output :

 Item 1
 Item 2
 Item 3

Using the declare keyword (command) to create the list , which is technically called an array :

declare -a List=(
                 \"element 1\" 
                 \"element 2\" 
                 \"element 3\"
                )
for entry in \"${List[@]}\"
   do
     echo \"$entry\"
   done

Out put :

element 1
element 2
element 3

Creating an associative array . A dictionary :

declare -A continent

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

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

Output :

 Argentina is in America
 Vietnam is in Asia
 France is in Europe

CVS variables or files in to a list .
Changing the internal field separator from a space , to what ever you want .
In the example below it is changed to a comma

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

Output :

Item 1
Item 2
Item 3

If need to number them :

` 

this is called a back tick . Put the command inside back ticks .

`commend` 

It is next to the number one on your keyboard and or above the tab key . On a standard american english language keyboard .

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

Out put is :

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

Becoming more familiar with bashes behavior :

Create a list in a file

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

Read the list file in to a list and display

List=$(cat List_entries.txt)
echo $List
echo \'$List\'
echo \"$List\"
echo ${List[*]}
echo \'${List[*]}\'
echo \"${List[*]}\"
echo ${List[@]}
echo \'${List[@]}\'
echo \"${List[@]}\"

BASH commandline reference manual : Special meaning of certain characters or words to the shell.



回答6:

You can use the syntax of ${arrayName[@]}

#!/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


回答7:

This is also easy to read:

FilePath=(
    \"/tmp/path1/\"    #FilePath[0]
    \"/tmp/path2/\"    #FilePath[1]
)

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


回答8:

Surprised that nobody\'s posted this yet -- if you need the indices of the elements while you\'re looping through the array, you can do this:

arr=(foo bar baz)

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

Output:

0 foo
1 bar
2 baz

I find this a lot more elegant than the \"traditional\" for-loop style (for (( i=0; i<${#arr[@]}; i++ ))).

(${!arr[@]} and $i don\'t need to be quoted because they\'re just numbers; some would suggest quoting them anyway, but that\'s just personal preference.)



回答9:

listOfNames=\"db_one db_two db_three\"
for databaseName in $listOfNames
do
  echo $databaseName
done

or just

for databaseName in db_one db_two db_three
do
  echo $databaseName
done


回答10:

The declare array doesn\'t work for Korn shell. Use the below example for the Korn shell:

promote_sla_chk_lst=\"cdi xlob\"

set -A promote_arry $promote_sla_chk_lst

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


回答11:

Implicit array for script or functions:

In addition to anubhava\'s correct answer: If basic syntax for loop is:

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

there is a special case in bash:

When running a script or a function, arguments passed at command lines will be assigned to $@ array variable, you can access by $1, $2, $3, and so on.

This can be populated (for test) by

set -- arg1 arg2 arg3 ...

A loop over this array could be written simply:

for item ;do
    echo \"This is item: $item.\"
  done

Note that the reserved work in is not present and no array name too!

Sample:

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: ....

Note that this is same than

for item in \"$@\";do
    echo \"This is item: $item.\"
  done

Then into a script:

#!/bin/bash

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

Save this in a script myscript.sh, chmod +x myscript.sh, then

./myscript.sh arg1 arg2 arg3 ...
Doing something with \'arg1\'.
Doing something with \'arg2\'.
Doing something with \'arg3\'.
Doing something with \'...\'.

Same in a function:

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

Then

myfunc item1 tiem2 time3
Working about \'item1\'.
Working about \'tiem2\'.
Working about \'time3\'.


回答12:

If you are using Korn shell, there is \"set -A databaseName \", else there is \"declare -a databaseName\"

To write a script working on all shells,

 set -A databaseName=(\"db1\" \"db2\" ....) ||
        declare -a databaseName=(\"db1\" \"db2\" ....)
# now loop 
for dbname in \"${arr[@]}\"
do
   echo \"$dbname\"  # or whatever

done

It should be work on all shells.



回答13:

Simple way :

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}


回答14:

This is similar to user2533809\'s answer, but each file will be executed as a separate command.

#!/bin/bash
names=\"RA
RB
R C
RD\"

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


回答15:

Possible first line of every Bash script/session:

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

Use e.g.:

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

May consider: echo interprets -e as option here



回答16:

Single line looping,

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

you will get an output like this,

db_a
db_b
db_c


回答17:

Try this. It is working and tested.

for k in \"${array[@]}\"
do
    echo $k
done

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


回答18:

I loop through an array of my projects for a git pull update:

#!/bin/sh
projects=\"
web
ios
android
\"
for project in $projects do
    cd  $HOME/develop/$project && git pull
end