Add value to array using Bash script - arrays

I have written the following script ,
#!/bin/bash
My_File=Image.csv
Value=YES
cat "$My_File" | while IFS=, read first last
do
echo "first='$first' last='$last'"
if [ "$last" == "$Value" ];
then
echo Match_Found
echo $first
array+=("$first")
echo $first is Added
fi
done
echo (${#array[#]})
It dosenot add any value to the array , Could someone point out to the issue .
The Input is as follow ,
FA_2015-01_666,NO
FA_2015-01_777,YES
FA_2015-01_888,NO
FA_2015-01_999,YES
FA_2015-01_555,YES

Redirect the file in, don't pipe from cat or the loop is run in a subshell and everything in it is lost when it ends.
#!/bin/bash
My_File="Image.csv"
Value=YES
while IFS=, read first last
do
if [ "$last" == "$Value" ];
then
echo Match_Found
echo $first
array+=("$first")
echo $first is Added
fi
done < "$My_File"
echo "${#array[#]}"

I haven't done some bash coding in some time, but it should be like this (The way i do it):
#our table to insert an item to
table=( )
tableLength=${#table[#]}
#inserting items
table[$tableLength]="foo"
#you have to refresh this variable everytime
tableLength=${#table[#]}
table[$tableLength]="bar"
#or you can do this without refreshing the length variable
table[${#table[#]}]="foobar"
I recommend you use:
table=()
table[${#table[#]}]="item!"
using # as the length, and table[#] to display all items, so it gets the length of the array and sets an item to the length of an array or table

Related

How do I gather user input in a loop, and then use a loop to access that input? [duplicate]

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
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"
)
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.
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=0; i<${arraylength}; i++ ));
do
echo "index: $i, value: ${array[$i]}"
done
Output:
index: 0, value: one
index: 1, value: two
index: 2, value: three
Yes
for Item in Item1 Item2 Item3 Item4 ;
do
echo $Item
done
Output:
Item1
Item2
Item3
Item4
To preserve spaces; single or double quote list entries and double quote list expansions.
for Item in 'Item 1' 'Item 2' 'Item 3' 'Item 4' ;
do
echo "$Item"
done
Output:
Item 1
Item 2
Item 3
Item 4
To make list 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[*]}
Output:
Item1 Item2 Item3
Loop through the list:
for Item in ${List[*]}
do
echo $Item
done
Output:
Item1
Item2
Item3
Create a function to go through a list:
Loop(){
for item in ${*} ;
do
echo ${item}
done
}
Loop ${List[*]}
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
Output:
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
CSV 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.
`command`
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
Output 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.
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
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
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')
I like the accepted answer also :) -- I've include these snippets as other helpful ways that also answer the question.
Including #!/bin/bash at the top of the script file indicates the execution environment.
It took me months to figure out how to code this simply :)
Other Sources
(while read loop)
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
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.)
This is also easy to read:
FilePath=(
"/tmp/path1/" #FilePath[0]
"/tmp/path2/" #FilePath[1]
)
#Loop
for Path in "${FilePath[#]}"
do
echo "$Path"
done
I used this approach for my GitHub updates, and I found it simple.
## declare an array variable
arr_variable=("kofi" "kwame" "Ama")
## now loop through the above array
for i in "${arr_variable[#]}"
do
echo "$i"
done
You can iterate through bash array values using a counter with three-expression (C style) to read all values and indexes for loops syntax:
declare -a kofi=("kofi" "kwame" "Ama")
# get the length of the array
length=${#kofi[#]}
for (( j=0; j<${length}; j++ ));
do
print (f "Current index %d with value %s\n" $j "${kofi[$j]}")
done
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}
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
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'.
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
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]}
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"
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.
What I really needed for this was something like this:
for i in $(the_array); do something; done
For instance:
for i in $(ps -aux | grep vlc | awk '{ print $2 }'); do kill -9 $i; done
(Would kill all processes with vlc in their name)
How you loop through an array, depends on the presence of new line characters. With new line characters separating the array elements, the array can be referred to as "$array", otherwise it should be referred to as "${array[#]}". The following script will make it clear:
#!/bin/bash
mkdir temp
mkdir temp/aaa
mkdir temp/bbb
mkdir temp/ccc
array=$(ls temp)
array1=(aaa bbb ccc)
array2=$(echo -e "aaa\nbbb\nccc")
echo '$array'
echo "$array"
echo
for dirname in "$array"; do
echo "$dirname"
done
echo
for dirname in "${array[#]}"; do
echo "$dirname"
done
echo
echo '$array1'
echo "$array1"
echo
for dirname in "$array1"; do
echo "$dirname"
done
echo
for dirname in "${array1[#]}"; do
echo "$dirname"
done
echo
echo '$array2'
echo "$array2"
echo
for dirname in "$array2"; do
echo "$dirname"
done
echo
for dirname in "${array2[#]}"; do
echo "$dirname"
done
rmdir temp/aaa
rmdir temp/bbb
rmdir temp/ccc
rmdir temp
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
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
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

storing user values in an array then comparing these variables using bash

while read line
do
if [ $line -ge $zero ]
then
a+=($line) ##here I am attempting to store the values in an array
else
for i in ${a[#]}
do
echo $(a[$i]) ## here I am trying to print them
done
fi
what is going wrong? it is giving this error:
a[1]: command not found
a[2]: command not found
a[3]: command not found
done
From the begining
if [ $line -ge $zero ]
what data type should be in $line?
-ge used in numeric comparison. If $line is a string than use = or if you just wnt to check that it's not empty use this syntax if [[ "$line" ]]
Next.
a+=($line)
Again if $line is a string then you should wrap in "" like this a+=("$line")
coz line can contain spaces.
For loop.
for i in ${a[#]}
do
echo $(a[$i]) ## here I am trying to print them
You'r messing with syntax here for i in ${a[#]} will iterate over arrays values, not indexes. And again if values are strings use "" like this for i in "${a[#]}"
So this echo $(a[$i]) won't work by 2 reasons. First you should use {} here, like this echo ${a[$i]}, second $i is not index, but it's may actualy work if it's a digit but in a wrong way. So here you need just echo $i coz $i is alredy a value from a array. Or rewrite foor loop.
for i in ${!a[#]}
do
echo ${a[$i]} ## here I am trying to print them
done
And last but not least, there is no done at the end of this script or it's just a part? So in the and it should look like this.
while read line; do
if [[ $line ]]; then
a+=( "$line" ) ##here I am attempting to store the values in an array
else
for i in ${!a[#]}; do
echo ${a[$i]} ## here I am trying to print them
done
fi
done < data.txt
echo ${a[#]} # print rusult

Using an array for input to while loop [duplicate]

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
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"
)
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.
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=0; i<${arraylength}; i++ ));
do
echo "index: $i, value: ${array[$i]}"
done
Output:
index: 0, value: one
index: 1, value: two
index: 2, value: three
Yes
for Item in Item1 Item2 Item3 Item4 ;
do
echo $Item
done
Output:
Item1
Item2
Item3
Item4
To preserve spaces; single or double quote list entries and double quote list expansions.
for Item in 'Item 1' 'Item 2' 'Item 3' 'Item 4' ;
do
echo "$Item"
done
Output:
Item 1
Item 2
Item 3
Item 4
To make list 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[*]}
Output:
Item1 Item2 Item3
Loop through the list:
for Item in ${List[*]}
do
echo $Item
done
Output:
Item1
Item2
Item3
Create a function to go through a list:
Loop(){
for item in ${*} ;
do
echo ${item}
done
}
Loop ${List[*]}
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
Output:
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
CSV 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.
`command`
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
Output 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.
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
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
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')
I like the accepted answer also :) -- I've include these snippets as other helpful ways that also answer the question.
Including #!/bin/bash at the top of the script file indicates the execution environment.
It took me months to figure out how to code this simply :)
Other Sources
(while read loop)
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
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.)
This is also easy to read:
FilePath=(
"/tmp/path1/" #FilePath[0]
"/tmp/path2/" #FilePath[1]
)
#Loop
for Path in "${FilePath[#]}"
do
echo "$Path"
done
I used this approach for my GitHub updates, and I found it simple.
## declare an array variable
arr_variable=("kofi" "kwame" "Ama")
## now loop through the above array
for i in "${arr_variable[#]}"
do
echo "$i"
done
You can iterate through bash array values using a counter with three-expression (C style) to read all values and indexes for loops syntax:
declare -a kofi=("kofi" "kwame" "Ama")
# get the length of the array
length=${#kofi[#]}
for (( j=0; j<${length}; j++ ));
do
print (f "Current index %d with value %s\n" $j "${kofi[$j]}")
done
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}
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
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'.
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
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]}
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"
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.
What I really needed for this was something like this:
for i in $(the_array); do something; done
For instance:
for i in $(ps -aux | grep vlc | awk '{ print $2 }'); do kill -9 $i; done
(Would kill all processes with vlc in their name)
How you loop through an array, depends on the presence of new line characters. With new line characters separating the array elements, the array can be referred to as "$array", otherwise it should be referred to as "${array[#]}". The following script will make it clear:
#!/bin/bash
mkdir temp
mkdir temp/aaa
mkdir temp/bbb
mkdir temp/ccc
array=$(ls temp)
array1=(aaa bbb ccc)
array2=$(echo -e "aaa\nbbb\nccc")
echo '$array'
echo "$array"
echo
for dirname in "$array"; do
echo "$dirname"
done
echo
for dirname in "${array[#]}"; do
echo "$dirname"
done
echo
echo '$array1'
echo "$array1"
echo
for dirname in "$array1"; do
echo "$dirname"
done
echo
for dirname in "${array1[#]}"; do
echo "$dirname"
done
echo
echo '$array2'
echo "$array2"
echo
for dirname in "$array2"; do
echo "$dirname"
done
echo
for dirname in "${array2[#]}"; do
echo "$dirname"
done
rmdir temp/aaa
rmdir temp/bbb
rmdir temp/ccc
rmdir temp
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
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
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

Splitting line of text into array at bash

I have a bunch of files named jtn216_<n>.o<m> where n and m are integer. The first one is assigned by me and the second one by the system. I need to check the last line at each file. I ran this to split that line into array
for i in {361..380}; do
v=$(tail -n 1 jtn216_$i.o*)
IFS=' ' read -ra line <<< "$v"
echo $line $v
done
3499200 3499200 87650.5574975270 13.6931802555886
1014400 1014400 87947.4382620423 13.9208064005841
3475800 3475800 87779.1695691355 13.8939964916376
3479200 3479200 87459.7284508034 13.7824644675699
3827800 3827800 87868.7538056652 13.8792123626210
2551600 2551600 87615.6417285010 13.8700006744178
3818400 3818400 87872.1788028955 13.8942371285402
3476800 3476800 87842.0543708163 13.9170342642747
3481800 3481800 87670.5841054385 13.8808556469308
2559200 2559200 87800.6530231416 13.8874423695824
3841600 3841600 87804.3972028423 13.8657419719638
916400 916400 87776.1342228681 13.8622746230494
3839000 3839000 87662.8185016707 13.8576498806465
3835200 3835200 87933.6917697832 14.0007327053153
3482000 3482000 88323.3509854563 13.9453990979062
3485400 3485400 87657.5078357100 13.8478805156354
3484800 3484800 87757.3379321554 13.8215034461609
3475400 3475400 87970.4729449120 13.9605031841208
3481800 3481800 87612.4211302676 13.8327950845915
2319400 2319400 87521.5669854330 13.8383953325475
I expected line to be an array not the first value from v. What am I doing wrong?
I think you're just printing line wrongly. Try echo "${line[#]}" instead.
You should address the contents of the array variable $line well e.g.
echo "${line[0]}"
echo "${line[*]}" # converts to a single string
echo "${line[#]}" # converts to multiple elements i.e. multiple arguments for echo
When an array variable is addressed without an index it would be just equivalent to getting the first element.
What bash calls "arrays" are really just a list of words (a list that can't even be nested). So if you simply output the array using echo, you're just asking it to output a list of arguments to echo. Consider:
echo foo bar # 'foo bar\n'
echo -n foo bar # 'foo bar'
x=( -n foo bar )
echo "${x[#]}" # 'foo bar'
If you output an array's name without any index or # or * component, you will get the first word* in that array:
echo "$x" # foo
So when you do echo $line $v what you're really saying is
echo ${line[0]} $v
Here's what you probably want:
for i in {361..380}; do
tail -n 1 jtn216_$i.o* | { # Pipe to a compound command to preserve assignments from read
IFS=' ' read -ra line
printf '[ '
printf '%s ' "${line[#]}"
printf ']\n'
}
done
Then you should see
[ 3499200 87650.5574975270 13.6931802555886 ]
[ 1014400 87947.4382620423 13.9208064005841 ]
[ 3475800 87779.1695691355 13.8939964916376 ]
…
*Wordsplit again since you didn't use quotes.
Try the following, if you want to get last line as array:
v=(`tail -n 1 jtn216_$i.o*`)
UPDATED
To accumulate line as array use:
v=(`tail -n 1 jtn216_$i.o*`)
line+=(${v[#]})
To output whole array:
${line[#]} or ${line[*]}
To count number of array elements:
${#line[#]} or ${#line[*]}

populate and read an array with a list of filenames

Trivial question.
#!/bin/bash
if test -z "$1"
then
echo "No args!"
exit
fi
for newname in $(cat $1); do
echo $newname
done
I want to replace that echo inside the loop with array population code.
Then, after the loop ends, I want to read the array again and echo the contents.
Thanks.
If the file, as your code shows, has a set of files, each in one line, you can assign the value to the array as follows:
array=(`cat $1`)
After that, to process every element you can do something like:
for i in ${array[#]} ; do echo "file = $i" ; done
declare -a files
while IFS= read -r
do
files+=("$REPLY") # Array append
done < "$1"
echo "${files[*]}" # Print entire array separated by spaces
cat is not needed for this.
#!/bin/bash
files=( )
for f in $(cat $1); do
files[${#files[*]}]=$f
done
for f in ${files[#]}; do
echo "file = $f"
done

Resources