8

I've written a bash script, which process multiple files. I now want to add support for a config file. This is my wanted data structure:

Array ( 
    [0] => Array (
        [name] => datset1
        [path] => /var/lib/bliTool/ds1
        [type] => cvs
    )

    [1] => Array (
        [name] => datset2
        [path] => /var/lib/bliTool/ds2
        [type] => xml
    )

    [2] => Array (
        [name] => datset3
        [path] => /home/igor/test/ds3
        [type] => cvs
    )
)

Q1 Is such a data structure possible within bash? Are there other recommendations? Remember, this should be in a config file...

Q2: I am thinking about one configuration file per 'set' like

/etc/myApp/
/etc/myApp/myApp.conf
/etc/myApp/datasets.d/
/etc/myApp/datasets.d/ds1.conf
/etc/myApp/datasets.d/ds2.conf
/etc/myApp/datasets.d/dsN.conf

and each /etc/myApp/datasets.d/dsN.conf file would look like

name=The DS name
path=/the/path/to/the/ds/files
type=thetype

What do you recommend? Is there a way to do everything in one file?

Q3: I want to support multiple path values per set. I could support something like

path="/first/path /second/path"

But I think I'll get trouble with spaces, so I should introduce a delimeter like

path="/first/path:/second/path"

to split the string.

Or is there a better way?

Igor
  • 191
  • 1
  • 2
  • 6

2 Answers2

15

You can't nest data strutures in bash. At best, you can store the names of associative arrays in an array, and jump through indirection hoops to access them.

$ declare -A aa0=([name]=dataset1 [path]=/var/lib/bliTool/ds1 [type]=cvs )
$ declare -A aa1=([name]=dataset2 [path]=/var/lib/bliTool/ds2 [type]=xml )
$ declare -A aa2=([name]=dataset3 [path]=/home/igor/test/ds3 [type]=cvs )

$ declare -a array=( aa0 aa1 aa2 )
$ tmp=aa0[name]
$ echo ${!tmp}
dataset1  

For the second question, it's certainly possible to define a configuration file format with sections, but you'll need to write a parser that can process it. Other languages typically have a library available to parse rich configuration file formats.

As far as multiple paths per variable, stick with :. In theory, any delimiter could be used as part of a path name component, and so the delimiter needs to be quoted if it is part of a path. But since PATH uses : as its delimiter, there is historical awareness that : is not a great character to use in a path name, and that it needs to be quoted in PATH-like parameters.

path="/first/poor\:path\:name:/second/bad\:path\:name"

Then it will be up to your application to process the back-slashed :.

chepner
  • 497,756
  • 71
  • 530
  • 681
  • 2
    I found this example very helpful but one question: how to iterate over the array named 'array' and then, for each element, access the 'name', 'path' and 'type' values? – Magallo Mar 10 '17 at 08:22
  • That's a good question, but it would be better posed as a separate question (which can reference this answer) rather than in a comment. – chepner Mar 10 '17 at 11:29
1

I came into a similar situation and my solution is to use different IFS within different level, it is somehow similar to chepner's idea. The code and sample can be found here https://github.com/pppoe/Nested-Array-Bash/

mr.pppoe
  • 3,945
  • 1
  • 19
  • 23