Score:0

How to separate different data values in a list and assign to variables in a shell script?

ca flag

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.

Score:3
ca flag

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
MissBrae avatar
ca flag
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.
NotTheDr01ds avatar
vn flag
@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.
Score:1
vn flag

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"
MissBrae avatar
ca flag
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 avatar
ca flag
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
NotTheDr01ds avatar
vn flag
@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.
MissBrae avatar
ca flag
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!
NotTheDr01ds avatar
vn flag
@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!
Score:0
it flag

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

mangohost

Post an answer

Most people don’t grasp that asking a lot of questions unlocks learning and improves interpersonal bonding. In Alison’s studies, for example, though people could accurately recall how many questions had been asked in their conversations, they didn’t intuit the link between questions and liking. Across four studies, in which participants were engaged in conversations themselves or read transcripts of others’ conversations, people tended not to realize that question asking would influence—or had influenced—the level of amity between the conversationalists.