0

Let's say I have a list of data in a shell script like this:

DataList = ["
Cat
Dog
Rabbit
GuineaPig
Hamster
"]

Now, how I would I go about setting each separate data value in the list as a variable? Like this:

$Value0 = "Cat"
$Valu1 = "Dog"
$Value2 = "Rabbit"
$Value3 = "GuineaPig"
$Value4 = "Hamster"

For the record, I am familiar with commandline utilities like Grep, AWK, and SED. However, I am not quite sure where to begin with something like this.

Also, for the record, my preferred shell is Fish, however feel free to answer in BASH or SH formatting. Don't worry, I can translate.

3 Answers 3

2

Not sure of what you Need. does this help?

#!/bin/bash
DataList=(
Cat
Dog
Rabbit
GuineaPig
Hamster
)

for i in {0..4}
do
    value[$i]=${DataList[$i]}
    echo "value[$i] = ${value[$i]}"
done

outputs:

value[0] = Cat
value[1] = Dog
value[2] = Rabbit
value[3] = GuineaPig
value[4] = Hamster
2
  • No, that does not help. I was looking for a way to parse the strings in the list and add them to separate variables. I meant what I wrote literally. I did not want to get a random string out of the list.
    – MissBrae
    Sep 12, 2021 at 20:28
  • @MissBrae To be fair, the solution here seems like it should be easily extendible to your use-case. If you have a fixed number of items (which it seems you must, if you are parsing them into static variables), then you could easily follow @jpbrain's example with $mem0 = $value[0]; $mem1= $value[1]; etc. I replaced "value" with "mem" since from other comments, that's what it sounds like you are trying to parse. Sep 15, 2021 at 15:56
1

Since your preferred shell is Fish, I'll offer three options.

First, given the DataList in a string format, you can use string split to split the individual lines into an actual list:

> set DataList "
  Cat
  Dog
  Rabbit
  GuineaPig
  Hamster
  "

> set --show DataList

$DataList: set in global scope, unexported, with 1 elements
$DataList[1]: |\nCat\nDog\nRabbit\nGuineaPig\nHamster\n|

> set Value (string split -n \n "$DataList")
> set --show Value

$Value: set in global scope, unexported, with 5 elements
$Value[1]: |Cat|
$Value[2]: |Dog|
$Value[3]: |Rabbit|
$Value[4]: |GuineaPig|
$Value[5]: |Hamster|

> echo $Value[2]

Dog

^ Blank lines in the example are purely for readability and do not appear in the actual output

But if you can, just embed the data as a list literal in the script anyway and avoid the extra string split:

> set DataList "Cat" \
  "Dog" \
  "Rabbit" \
  "GuineaPig" \
  "Hamster"

> set --show DataList

$DataList: set in global scope, unexported, with 5 elements
$DataList[1]: |Cat|
$DataList[2]: |Dog|
$DataList[3]: |Rabbit|
$DataList[4]: |GuineaPig|
$DataList[5]: |Hamster|

> echo $DataList[2]
Dog

Finally, your question, taken literally, is to separate the list into variables, rather than a variable containing a list. I assume that's not really what you meant. It would be a bit pathologic, IMHO, since you would lose the ability to easily count, iterate, and index the results, but it can be done ...

set DataList "
Cat
Dog
Rabbit
GuineaPig
Hamster
"

set v (string split -n \n "$DataList")

set scrpt (for i in (seq (count $v))
             echo 'set Value'(math $i-1) '"'$v[$i]'"'
           end)

eval (string join ";" $scrpt)
set --erase v
set --erase scrpt

Results in:

$Value0 = "Cat"
$Value1 = "Dog"
$Value2 = "Rabbit"
$Value3 = "GuineaPig"
$Value4 = "Hamster"
5
  • Thanks! That last one is exactly what I wanted! Perhaps my reason for needing to do this would explain why. I created a shell script to display system information such as processor model, memory count, system board model, as well as OS and kernel versions. I wanted to add a way to display the exact memory configuration, and not just the quantity, speed, and module count. E.g. Memory: 16 GB (8 GB x 2). I already have a function that parses dmidecode and sets the memory count as $MemoryCount and module count as $ModulesInstalled and $TotalModules. Now I have a place to start.
    – MissBrae
    Sep 12, 2021 at 20:34
  • Well... it looks like it should do what I wanted. But I keep getting errors when I try to run it. I'm not that familiar with for loops in Fish, so I couldn't debug it myself: ~/.local/ubin/test.fish (line 13): Unexpected end of string, quotes are not balanced set scrpt (for i in (seq (count $v)) echo 'set Value''(math $i-1) '"'$v[$i]'"' end) eval (string join ";" $scrpt) set --erase v scrpt ^ <W> fish: Error while reading file /home/braelin/.local/ubin/test.fish
    – MissBrae
    Sep 12, 2021 at 20:43
  • @MissBrae Ah yes, if it's record-parsing, then that makes sense. But probably better to post something more like the "real data" that you are using. The script could be even simpler. The problem with the quotes was my mistake -- I've fixed it. Note that Fish is nice enough to highlight the extra quote (at least the line) with the problem if you paste it in at the prompt. Sep 12, 2021 at 23:46
  • 1
    Thanks again, for the fix! I made my own edit... it seems the 'set --erase' command only expects 1 argument, and not more, so I separated into two lines. Now it works as described! I'll keep that in mind, to not simply the question. Perhaps I would have got better responses if I stated my actual problem. Now... to get to the work adding to my system information gathering script!
    – MissBrae
    Sep 14, 2021 at 19:30
  • @MissBrae Looks like set --erase with multiple values is a fairly recent edition in Fish 3.2. Don't forget to accept the answer -- Thanks! Sep 14, 2021 at 22:57
0

I'd keep the values in a colon-separated list, and use Stephen Collyer's "Bash Path Functions" and cut -d: -f3 or similar.

Here's my pre-written blob:

I use Stephen Collyer's bash_path_funcs, described in Linux Journal way back in 2000:

https://www.linuxjournal.com/article/3645 https://www.linuxjournal.com/article/3768 https://www.linuxjournal.com/article/3935

The addpath function adds an entry to a path only if it is not there in the first place. delpath -n deletes all non-existent directories from a path.

You can get the pathfunc.tgz file from https://web.archive.org/web/20061210054813/http://www.netspinner.co.uk:80/Downloads/pathfunc.tgz

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .