dictionaryassociative-arrayfish

fish shell --- how to simulate or implement a hash table, associative array, or key-value store


I am migrating from ksh to fish. I am finding that I miss the ability to define an associative array, hash table, dictionary, or whatever you wish to call it. Some cases can be simulated as in

set dictionary$key $value eval echo '$'dictionary$key

But this approach is heavily limited; for example, $key may contain only letters, numbers, and underscores.

I understand that the fish approach is to find an external command when one is available, but I am a little reluctant to store key-value information in the filesystem, even in /run/user/<uid>, because that limits me to "universal" scope.

How do fish programmers work around the lack of a key-value store? Is there some simple approach that I am just missing?

Here's an example of the sort of problem I would like to solve: I would like to modify the fish_prompt function so that certain directories print not using prompt_pwd but using special abbreviations. I could certainly do this with a switch command, but I would much rather have a universal dictionary so I can just look up a directory and see if it has an abbreviation. Then I could change the abbreviations using set instead of having to edit a function.


Solution

  • You can store the keys in one variable and values in the other, and then use something like

    if set -l index (contains -i -- foo $keys) # `set` won't modify $status, so this succeeds if `contains` succeeds
        echo $values[$index]
    end
    

    to retrieve the corresponding value.

    Other possibilities include alternating between key and value in one variable, though iterating through this is a pain, especially when you try to do it only with builtins. Or you could use a separator character and store a key-value pair as one element, though this won't work for directories because variables cannot contain \0 (which is the only possible separator for paths).