1

What I'm trying to do, is emulate a 2D array in a bash script on my application. (I'm an idiot for writing it in bash, but I'll re-write it once I have a working copy before my deadline)

My server.data file that I want to read from:

1:hello:there
2:im:a
3:computing:system

I know PHP ALOT better than bash, but here's a pseudo code of what I mean

foreach(line in server.data) {         
 arr = explode(":", server.data)  
  echo arr[0]    
  echo arr[1]  
  echo arr[2]  
  echo \n  
}

Would return these values:

1 hello there
2 im a
3 computing system

Can someone write a small bash script, explaining how to place each line into an array?

Alex Schittko
  • 53
  • 2
  • 7
  • PHP and bash are two completely different platforms. – Alex Schittko Jul 29 '12 at 14:33
  • The question has been asked as one line strings as far as I can find, not multiple strings in a file. PHP isn't installed on the machine this script has to run on, and I don't want to install PHP on the machine, because we're trying to keep our disk space as low as possible. And I asked for an explanation, not for someone to do my work for me. – Alex Schittko Jul 29 '12 at 14:38
  • You want 1 line per array element and all ":" replaced with space? – Leonid Volnitsky Jul 29 '12 at 15:05
  • Is there any reason you want an *array* ? – Karoly Horvath Jul 29 '12 at 15:16
  • To be precise - PHP and Bash are no platforms - one is a language the other one is a shell... a *platform* is something very else. – Martin Zeitler Dec 31 '12 at 09:21

5 Answers5

5
cat server.data | 
while read line; do  
   IFS=: 
   set - $line
   echo $1  
   echo $2  
   echo $3
done
Leonid Volnitsky
  • 8,854
  • 5
  • 38
  • 53
  • 4
    Useless use of cat: `while read line; do ...; done < server.data`. – chepner Jul 29 '12 at 14:57
  • I like my pipes in this order. And it is not useless - it makes this script multithreaded – Leonid Volnitsky Jul 29 '12 at 15:00
  • 1
    Also, I'm always nervous I'll mistype the < or > and erase the entire file. `cat` makes life simple – David Jul 29 '12 at 15:01
  • 2
    It's not multithreaded; it forces you to spawn an extra process for no reason. – chepner Jul 29 '12 at 15:04
  • This extra process is doing file reading, and bash does parsing - ok, not multithreaded, but parallel processing. In many cases I found it to be faster. – Leonid Volnitsky Jul 29 '12 at 15:07
  • 1
    @Leonid Volnitsky: have you actually measured it? please post a code which is faster with it. – Karoly Horvath Jul 29 '12 at 15:10
  • 1
    Instead of reading directly from the file (which the OS will already buffer), you're creating another new buffer (for the pipe) that holds the output of `cat` until `bash` is ready to read from it. – chepner Jul 29 '12 at 15:17
  • @KarolyHorvath: - no didn't done any measurements. BTW, I've just posted on SO new question about this - http://stackoverflow.com/questions/11710552/useless-use-of-cat – Leonid Volnitsky Jul 29 '12 at 15:48
  • 1
    See [Useless use of cat?](http://stackoverflow.com/questions/11710552/useless-use-of-cat) – Leonid Volnitsky Aug 06 '13 at 18:50
4

A more general answer: If you want to imitate php's "explode" in bash with both just a string (or data coming from a file) you can use something like:

#!/bin/bash
# explode functionality in bash

data="one:two:three:and 4"

echo $data | while read line; do
   IFS=:
   set - $line
   echo $1
   echo $2
   echo $3
   echo $4
done

If your data comes on the other hand from a file, then you can redirect the contents of a file to the while loop:

  #!/bin/bash
  # explode 

  filename="data"

  while read line; do
     IFS=:
     set - $line
     echo $1
     echo $2
     echo $3
     echo $4
  done < $filename

This redirect is better than cat $filename into the while loop, because it does not need to fork another process.

Ingo Baab
  • 528
  • 4
  • 7
0

Assuming the text file is called "x.txt":

#!/bin/bash

for line in `cat x.txt`; do
    a[${i}]=$line;
    i=$i+1;
done;

echo ${a[0]};
echo ${a[1]};
echo ${a[2]};
Michael Besteck
  • 2,415
  • 18
  • 10
  • This is wrong in a few ways. Never use `for` to iterate over the lines in a file. The dollar sign and curly braces aren't necessary in the array subscript. `i=$i+1` results in an increasingly long string that looks like "+1+1+1+1+1+1+1". In any case it's not necessary to use a subscript to append to an array: `array+=(element)`. Also, too many semicolons. – Dennis Williamson Jul 29 '12 at 20:14
0
while IFS=: read -a arr; do
    echo "${a[@]}"
    echo -n "${arr[0]} "
    echo -n "${arr[1]} "
    echo "${arr[2]}"
done < server.data

The echo statements just demonstrate some ways to access the array; all the work is done by read -a.

chepner
  • 497,756
  • 71
  • 530
  • 681
0

This gives you an pseudo-2D array where you can access the individual elements by concatenating each dimension-index:

while read line
do
    ((i++))
    j=0
    IFS=:
    for e in $line
    do
        ((j++))
        lines["$i$j"]=$e
    done
done < data.txt

echo ${lines[@]}
1 hello there 2 im a 3 computing system
echo ${lines[12]}
hello
tzelleke
  • 15,023
  • 5
  • 33
  • 49