LinuxQuestions.org
Download your favorite Linux distribution at LQ ISO.
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices

Reply
 
LinkBack Search this Thread
Old 01-04-2008, 01:17 PM   #1
jakeo25
LQ Newbie
 
Registered: Jan 2008
Location: Boulder, CO
Distribution: Ubuntu Gusty / Fiesty
Posts: 7

Rep: Reputation: 0
Thumbs up bash: Passing arrays with spaces


All,

I am in a bit of a pickle over this one. I have arrays of strings I need to pass to a function. The problem is that when an array element has a space, this is now treated as a new array element, due to the echo-ing process, parameter-passing paradigm.

Here is sample:

-----------------------------------------------------------
#!/bin/bash
myarray=( "one 1" "two2" "three 3")

function myArrayFunction ()
{
LIST=( `echo "$1"` )
echo "Array size is ${#LIST[*]}"
for A in $(seq 0 $((${#LIST[*]} - 1))); do
echo "${LIST[$A]}"
done
}

echo "Initial array size is ${#myarray[*]}"

argument=`echo ${myarray[*]}`
myArrayFunction "$argument"
------------------------------------------------------------

output of this is

Initial array size is 3
Array size is 5
one
1
two2
three
3

Perhaps I have missed some trick that could help?

Jake
 
Old 01-04-2008, 03:13 PM   #2
jozyba
Member
 
Registered: Sep 2007
Distribution: Debian Etch, Lenny, Lenny/Sid
Posts: 31

Rep: Reputation: 15
You've emptied out the contents of an array with 3 elements into a string called 'argument'. Then, using the white space, you've split the string up into 5 separate "words" and asigned them one by one to the array called 'LIST'.

It would be simpler if you avoided all that unnecessary juggling from one variable to another:
Code:
#!/bin/bash

myarray=( "one 1" "two2" "three 3")

function myArrayFunction () {
    echo "Array size is ${#myarray[*]}"
    for A in $(seq 0 $((${#myarray[*]} - 1))); do
        echo "${myarray[$A]}"
    done
}

echo "Initial array size is ${#myarray[*]}"

myArrayFunction
 
Old 01-04-2008, 03:26 PM   #3
jakeo25
LQ Newbie
 
Registered: Jan 2008
Location: Boulder, CO
Distribution: Ubuntu Gusty / Fiesty
Posts: 7

Original Poster
Rep: Reputation: 0
Angry

Perhaps I was not clear with my post, as your solution suggests.

In order to pass an array to a function, use the lines

argument=echo "${array[@}}"
MyArrayFunction $argument

Yes, I understand what this is doing. What I am asking is that I will be passing several arrays to MyArrayFunction, each with different sizes and one or more spaces in the elements.

I could explicitly type in the array as you suggest, but as a C programmer, I like to avoid repeating code and potential typing mistakes in a large script.

jakeo25
 
Old 01-04-2008, 04:36 PM   #4
radoulov
Member
 
Registered: Apr 2007
Location: Milano, Italia/Варна, България
Distribution: Ubuntu, Open SUSE
Posts: 212

Rep: Reputation: 34
Something ugly like this:

Code:
$ declare -f afnc
afnc ()
{
    local args=($(IFS='
';printf "%s\n" "$@"));
    printf "Array size is %d\n" ${#args[@]};
    for ((i=0; i<${#args[@]}; i++))
    do
        printf "%s\n" "${args[i]}";
    done
}

$ array=("o n e" two "thr ee" "fo ur")

$ afnc "${array[@]}"
Array size is 4
o n e
two
thr ee
fo ur
With zsh it would be easier.

Last edited by radoulov; 01-04-2008 at 04:44 PM. Reason: Modified.
 
Old 01-04-2008, 05:45 PM   #5
jozyba
Member
 
Registered: Sep 2007
Distribution: Debian Etch, Lenny, Lenny/Sid
Posts: 31

Rep: Reputation: 15
Code:
#!/bin/bash

myarray=( "one 1" "two2" "three 3" )

function myArrayFunction ()
{
    y=$#
    for (( x=0; x<y; x++ )); do
        LIST[x]="$1"
        shift
    done
    echo "Array size is ${#LIST[*]}"
    for (( A=0; A<${#LIST[*]}; A++ )); do
        echo "$A = ${LIST[$A]}"
    done
}

echo "Initial array size is ${#myarray[*]}"

argument=( "${myarray[@]}" )
myArrayFunction "${argument[@]}"

Last edited by jozyba; 01-04-2008 at 06:15 PM.
 
Old 01-05-2008, 04:06 AM   #6
radoulov
Member
 
Registered: Apr 2007
Location: Milano, Italia/Варна, България
Distribution: Ubuntu, Open SUSE
Posts: 212

Rep: Reputation: 34
Or (I definitely need more coffee ):

Code:
$ afnc (){
> printf "Array size is %d\n" "${#@}";
> printf "%s\n" "$@"
> }
$ array=("o n e" two "thr ee" "fo ur")
$ afnc  "${array[@]}"
Array size is 4
o n e
two
thr ee
fo ur

Last edited by radoulov; 01-05-2008 at 04:21 AM.
 
Old 01-05-2008, 11:55 AM   #7
jakeo25
LQ Newbie
 
Registered: Jan 2008
Location: Boulder, CO
Distribution: Ubuntu Gusty / Fiesty
Posts: 7

Original Poster
Rep: Reputation: 0
Simple, elegant & clever. The only question is why I didn't think of that.

ty,

j
 
Old 01-07-2008, 11:32 AM   #8
jakeo25
LQ Newbie
 
Registered: Jan 2008
Location: Boulder, CO
Distribution: Ubuntu Gusty / Fiesty
Posts: 7

Original Poster
Rep: Reputation: 0
Thumbs up

Just an FYI to those who are reading this topic.

1) The lines

argument=( "${myarray[@]}" )
myArrayFunction "${argument[@]}"

could be combined:

myArrayFunction "${myarray[@]}"

2) It was interesting to observe the differences with dereference parameters '@' and '*', e.g.

myArrayFunction "${myarray[*]}" # ERROR: entire array as a single element

myArrayFunction "${myarray[@]}" # works!

The positional parameters' rules apply here, from the "Advanced BASH scripting Guide":

$* All of the positional parameters, seen as a single word

$@ Same as $*, but each parameter is a quoted string ... each parameter in the argument list is seen as a separate word.
 
Old 06-05-2009, 08:00 AM   #9
rambutan
LQ Newbie
 
Registered: May 2007
Location: Ridgeland, WI USA
Distribution: Ubuntu
Posts: 5

Rep: Reputation: 0
IFS=$'\n' --- changes break point for the array

Here is a similar script I wrote to use ls to fill an array.

#!/bin/bash

IFS=$'\n'
### VERY IMPORTANT - changes break point for arrays!!! no break on spaces

ArrayFiles=(`ls /Data/Writer/Linux-Computers/ --format=single-column -p | grep -v /`)
# what's it do?
# ls --format=single-column ===> output is a single column, not folded multiple columns
# ls -p ===> output appends the "/" to the end of any directory names
# grep -v / ===> means select all EXCEPT lines with / --- this means ignore the directories

# echo the element count
element_count=${#ArrayFiles[*]}
echo "There are $element_count elements in the array"

# make a loop to show the records
i="0"
while [ $i -lt $element_count ]
do
echo $i \> ${ArrayFiles[$i]}
# step by 1
i=$[$i+1]
done
 
  


Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off
Trackbacks are Off
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
passing variable from bash to perl in a bash script quadmore Programming 6 02-21-2011 04:11 AM
bash arrays question introuble Programming 1 05-20-2006 03:07 AM
Passing bidimensional arrays to function in C pittopitto Programming 5 05-18-2006 09:31 AM
perl: passing 2 individual arrays/lists as args johnMG Programming 12 04-18-2005 03:49 PM
bash for statement with 2 arrays? Noerr Linux - General 10 05-27-2002 12:58 PM


All times are GMT -5. The time now is 03:04 PM.

Main Menu
 
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
identi.ca: @linuxquestions
Facebook: @linuxquestions
Open Source Consulting | Domain Registration