[HN Gopher] Today I learned that bash has hashmaps (2024)
       ___________________________________________________________________
        
       Today I learned that bash has hashmaps (2024)
        
       Author : stefankuehnel
       Score  : 138 points
       Date   : 2025-01-08 07:07 UTC (3 days ago)
        
 (HTM) web link (xeiaso.net)
 (TXT) w3m dump (xeiaso.net)
        
       | aunderscored wrote:
       | Not only do they exist, but they have some fantastic foot guns!
       | https://mywiki.wooledge.org/BashPitfalls#A.5B.5B_-v_hash.5B....
        
         | stefankuehnel wrote:
         | Interesting, definitely need to keep that in mind.
        
         | forgotpwd16 wrote:
         | >they have some fantastic foot guns!
         | 
         | Otherwise wouldn't be getting the full shell experience.
        
           | miohtama wrote:
           | It's not like we would have 50 years of good programming
           | language design and then stick to things that were created 50
           | years ago.
        
           | echelon wrote:
           | Why hasn't shell scripting evolved? It's god-awful.
        
             | Analemma_ wrote:
             | - bash is available pretty much everywhere, so if you learn
             | it you can always use it, whereas if you learn a weird new
             | shell you'll be occasionally forced to fall back on bash
             | anyway, so people learn just bash for efficiency's sake
             | (because learning one shell is painful enough as it is).
             | And any proposed replacement will be non-portable.
             | 
             | - some of the things that make shell scripting terrible
             | can't be fixed in the shell itself, and need changes to the
             | entire ecosystem of console applications. e.g. it would be
             | awesome if every Unix utility output structured data like
             | JSON which could be parsed/filtered, instead of the soup of
             | plaintext that has to be memorized and manipulated with
             | awk, but that almost certainly won't happen. There's a
             | bunch of backward-compatibility requirements like VT-100
             | and terminal escape sequences limiting the scope of
             | potential improvements as well
             | 
             | - there's a great deal of overlap between "people who do a
             | lot of shell scripting" and "people who are suspicious of
             | New Stuff and reluctant to try it"
        
             | azriel91 wrote:
             | https://www.nushell.sh/
             | 
             | I use this as my main shell on Windows, and as a
             | supplementary on Mac and Linux.
        
             | vessenes wrote:
             | What would you like to see?
             | 
             | I'd guess there's a solution to almost any set of
             | priorities you have for shell scripting.
             | 
             | The domain space is extremely challenging: by default,
             | executing any program on behalf of the caller using
             | arbitrary text inputs, and interpreted.
             | 
             | All modern shells allow calling of literally any binary
             | using the #!/usr/bin/env randombinary incantation.
             | 
             | Upshot: bash has its place, and while some of that place is
             | unearned inertia, much of it is earned and chosen often by
             | experienced technologists.
             | 
             | In my case, if I'm doing a lot of gluing together of text
             | outputs from binaries, bash is my go-to tool. It's
             | extremely fast and expressive, and roughly 1/4 the length
             | of say python and 1/8 the length of say go.
             | 
             | If I'm doing a lot of logic on text: python. Deploying lots
             | of places/different architectures: go
        
         | wruza wrote:
         | A comment worth more than a post, thanks!
        
         | chengiz wrote:
         | Too many. I still write /bin/sh syntax (I know it's a symlink
         | to bash now but I mean the old school sh). Anything that
         | requires bash-that-isnt-sh is usually better written in perl or
         | something else.
        
         | rqtwteye wrote:
         | "fantastic foot guns"
         | 
         | It wouldn't be a worthy bash feature if after learning about it
         | you wouldn't spend a few days figuring out why the damn thing
         | doesn't work the way it works in any other language.
        
       | oniony wrote:
       | A couple of weeks ago I learnt that Bash on Mac does not have
       | associative arrays. We worked around the issue by changing the
       | script to run under Zsh, but beware.
        
         | ptdorf wrote:
         | Sounds like a bash 3 issue.
         | 
         | $ bash --version
         | 
         | GNU bash, version 5.2.32(1)-release (aarch64-apple-
         | darwin23.4.0)
         | 
         | $ declare -A aaa; aaa[a]=a; aaa[b]=bb; for i in ${!aaa[@]}; do
         | echo "$i --> ${aaa[$i]}"; done
         | 
         | b --> bb
         | 
         | a --> a
        
           | forgotpwd16 wrote:
           | To elaborate on this, macOS default bash is still stuck
           | (assuming due to licensing) in v3.2.x (released in 2007).
           | Bash got associative arrays in v4 (released in 2009).
        
         | x3n0ph3n3 wrote:
         | You should be getting bash from homebrew anyways.
        
           | pletnes wrote:
           | Just use the included zsh.
        
             | tgv wrote:
             | I like my scripts to run on both linux and macos. It's
             | somewhat limiting, but it saves trouble.
        
               | pletnes wrote:
               | Linuxes have zsh. If you install zsh on linux or bash on
               | macos, hassle is same ish. Installing homebrew is
               | required but I always do it myself. Although bash is more
               | often the available shell on cloud services.
        
               | pletnes wrote:
               | Also, most bash scripts run as zsh scripts.
        
           | eadmund wrote:
           | Or using an OS which doesn't ship ancient software. Linux
           | exists. It's pretty awesome.
        
             | wruza wrote:
             | Only until you find that your requirement or use case
             | doesn't work in it.
        
             | tgv wrote:
             | There's a time and place for evangelism. This isn't it.
        
         | teddyh wrote:
         | Many programs on macOS are stuck in the ancient past, due to
         | Apple:
         | 
         | <https://web.archive.org/web/20240810094701/https://meta.ath0..
         | .>
        
       | agnishom wrote:
       | > Q: How do I declare a Hashmap?
       | 
       | > A: You use the command `declare -A HASHMAP_NAME`
       | 
       | This is why I think Bash is a horrible language
        
         | jolmg wrote:
         | Because of the -A instead of an -H? -A is for "Associative
         | array".
        
         | arter4 wrote:
         | what do you mean?
        
           | agnishom wrote:
           | Just that it is ugly and strange
        
             | gapan wrote:
             | I don't know about that.
             | std::unordered_map<std::string, int> myHashMap;
             | 
             | looks a lot uglier and stranger to me.
        
       | teddyh wrote:
       | It's amazing how much of a superpower merely _reading the manual_
       | is nowadays.
       | 
       | <https://www.gnu.org/software/bash/manual/bash.html#Arrays>
        
         | latexr wrote:
         | While I agree with the larger sentiment I think you're making
         | (I also make it a habit to peruse the manual just to see what
         | is available), how often do you _reread_ the manual, especially
         | for your shell? I knew about associative arrays in bash, but
         | not by reading the manual as those were introduced in v4 and
         | I've been using bash for longer than that.
        
           | teddyh wrote:
           | You should probably read the release notes for new major
           | versions. Also, anytime you think " _I wish there was
           | <feature> available in this program_", you should probably
           | double-check if such a feature has appeared since you last
           | learned the program.
        
             | dredmorbius wrote:
             | That's how I discovered the '&' regex feature in less some
             | years back.
        
               | teddyh wrote:
               | Do you mean PCRE's "(?&name)" feature? That is not
               | portable; for instance, Python calls it "(?P=name)". Or
               | do you mean the common feature of "&" _in the replacement
               | string_ meaning "the whole matched string"? While this
               | feature is common in languages which use regexps
               | (including ed, sed, awk, etc.), that's not actually a
               | _regexp_ feature, since the  & character has that effect
               | in the _replacement string_ , not in the regular
               | expression. It is also not always portable; for instance,
               | Emacs requires escaping as \& for the character to have
               | the special feature.
        
               | dredmorbius wrote:
               | From man(1) less:                 &pattern
               | Display  only  lines which match the pattern; lines which
               | do not            match the pattern are not displayed.
               | If pattern  is  empty  (if            you  type  &
               | immediately  followed  by ENTER), any filtering is
               | turned off, and all lines are displayed.  While filtering
               | is  in            effect,  an  ampersand  is  displayed
               | at  the  beginning of the            prompt, as a
               | reminder that some lines in the file may be hidden.
               | $ less --version       less 487 (GNU regular expressions)
               | Copyright (C) 1984-2016  Mark Nudelman
        
         | dredmorbius wrote:
         | TBF, the Bash manpage now runs > 80 pages:                 man
         | -Tps bash | ps2pdf - bash.pdf
         | 
         | That can be daunting. Though illuminating.
        
         | wruza wrote:
         | My one-shot memory worsened with years but grasping concepts
         | from examples got much better due to experience. So I find
         | walls of text _much_ less useful than a continuous "synopsis"
         | of snippets and best practices. One usage example is worth a
         | hundred of words and few pages of it may be worth a whole
         | manual, especially when "at hand" through editor means. For
         | bash idk if that exists on the internet, so I maintain my own
         | in my one big text file. I wish every manual had the synopsis-
         | only section (maybe I should just LLM these).
        
           | farrelle25 wrote:
           | > _One usage example is worth a hundred words ... For bash
           | idk if that exists on the internet, ..._
           | 
           | Totally agree with that - I maintain a big txt file too.
           | 
           | Maybe this bash compendium is a bit similar:
           | 
           | https://www.commandlinefu.com/commands/browse
        
           | teddyh wrote:
           | You might like these:
           | 
           | * <https://learnxinyminutes.com/>
           | 
           | And some code search engines:
           | 
           | * Debian: <https://codesearch.debian.net/>
           | 
           | * Python: <https://www.programcreek.com/python/>
           | 
           | * Linux: <https://livegrep.com/search/linux>
           | 
           | * GitHub: <https://grep.app/>
           | 
           | * HTML, JS and CSS: <https://publicwww.com/>
        
         | johannes1234321 wrote:
         | Bash is low on the list of things to learn, especially as many
         | greybeards suggest keeping on POSIX compatibility and/or using
         | a "proper" language (Python, older: Perl) for anything longer
         | than a few lines.
        
           | jeltz wrote:
           | They suggest that based on their experience. Error handling
           | in bash is awful so I advice against using it for anything
           | complex.
        
             | irunmyownemail wrote:
             | Anything complex should be written in a competent language
             | like Java. Script languages (like Bash and Python) are for
             | short (a few lines long) scripts. Using the tool outside
             | the scope of what it was designed for is not a good idea.
        
               | teddyh wrote:
               | Tell me you have never seriously used Python without
               | telling me you have never seriously used Python.
               | 
               | I mean, viewing Python strictly as a _scripting_
               | language? I am honestly lost for words. There are many
               | huge and major applications and web sites written in
               | Python, _without_ people regretting it after the fact.
               | And yet here you are dismissing it out of hand without a
               | single argument.
        
               | Izkata wrote:
               | Meanwhile most of the time topics like this come up and
               | people hate on shell scripts, those of us that like them
               | see those criticisms the same way you're looking at this
               | comment about python: So far out there it's almost not
               | worth responding. I think that's why GGP and GGGP think
               | "greybeards" don't think it's worthwhile based on
               | experience - it's actually not worth arguing against
               | misinformed comments so newer people don't realize it's
               | still heavily used, just quietly in the background for
               | things it's actually good at.
               | 
               | Further down is a comment about that:
               | https://news.ycombinator.com/item?id=42664939
        
               | dingnuts wrote:
               | Don't be too rude, this is a common view among people who
               | are technically adjacent but not engineers, like IT
               | people. It's an incorrect superstition, of course, but in
               | tech almost everybody has their superstitions. There's no
               | reason to be rude -- ignorance is not a crime.
        
               | chillpenguin wrote:
               | I see that kind of thing all the time. Usually it is
               | about static types. People think that dynamic languages
               | aren't "serious", or something. It is laughable that
               | these people still make up a significant amount of
               | comments, here in 2024.
        
               | TypingOutBugs wrote:
               | Why shouldn't you use Python for larger projects, and why
               | do so many startups succeed with large Python repos?
        
               | dotancohen wrote:
               | When my scripts outgrow bash, they almost always wind up
               | in Python.
               | 
               | That said, Sonnet 3.5 had gotten me much further in bash
               | than was possible before - and it's all really
               | maintainable too. I highly suggest consulting with Sonnet
               | on your longer scripts, even just asking it "what would
               | you suggest to improve".
        
             | superq wrote:
             | You can go a really really long way, with a script that
             | will work everywhere, with just _set -e_ and aborting at
             | the first error.
             | 
             | Better yet, 'bash unofficial strict mode':
             | set -euo pipefail         IFS=$'\n\t'
        
           | superq wrote:
           | Give bash some credit - it's actually amazing for even very
           | large, complex systems (of which there are many -- quietly
           | doing their jobs for decades.)
           | 
           | With xargs or GNU parallel, you can have multi-processing,
           | too. Combining with curl or ffmpeg, you can literally build a
           | production-grade web scraper or video transcoding pipeline in
           | a couple of minutes and a few dozen lines of code.
        
       | crabbone wrote:
       | To me, this is a development in the wrong direction. Shell is
       | great precisely because it's so minimal. Everything is string
       | rule is one that calms all of your type-induced fears.
       | 
       | Having to implement hash-tables, while still keeping the
       | appearances of everything being a string is the anti-pattern
       | known as "string programming" (i.e. when application develops a
       | convention about storing type / structure information inside
       | unstructured data, often strings).
       | 
       | I would love for there to be a different system shell with a
       | small number of built-in types that include some type for
       | constructing complex types. There are many languages that have
       | that kind of type system: Erlang, for example. But, extending
       | Unix Shell in this way is not going to accomplish this.
        
         | latexr wrote:
         | > To me, this is a development in the wrong direction.
         | 
         | That ship has sailed. These were introduced in Bash 4, released
         | in 2009, and Bash is already on version 5.
        
           | mhd wrote:
           | Isn't this basically the same feature that existed in ksh93?
        
       | biorach wrote:
       | Every few years I rediscover this fact and every few years I do
       | my best to forget it
        
       | j45 wrote:
       | For some tasks, if as much as possible was coded in bash, it
       | would work being called anywhere from any programming language.
       | 
       | Now to add hashtables to that.
        
       | somat wrote:
       | I love shell, I think it's killer feature are pipes and whoever
       | figured out how to design so you can pipe in and out of control
       | structures(Doug Mcilroy?) is a goddamn genius. however, after
       | writing one to many overly clever shell scripts, I have a very
       | clearly delineated point in which the script has become too
       | complex and it is time to rewrite in a language better suited for
       | the task. and that point is when I need associative arrays.
       | 
       | A lot of the sins of shell are due to it's primary focus as an
       | interactive language. Many of those features that make it so nice
       | interactively really hurt it as a scripting language.
        
         | DSpinellis wrote:
         | Pipe-related concepts in various restricted forms were floating
         | around for years. Doug McIlroy indeed proposed them in 1964 and
         | was heading the Bell Labs team when they were implemented in
         | the Third Research Edition of Unix (1973).
         | 
         | See https://youtu.be/FbDebSinSQo?si=xbWIqES80hI2S802&t=901
        
           | emmelaich wrote:
           | Sure, but in and out of control structures? I think that's
           | the major point your parent was making.
        
         | orbisvicis wrote:
         | Control structures? Do you mean something like '{ cmd1 || cmd2;
         | } | cmd3', where the control structures are the braces?
        
       | dghf wrote:
       | Picky and probably pointless question: are they actually
       | hashmaps? If I understand correctly, a hashmap isn't the only way
       | to implement an associative array.
        
         | zabzonk wrote:
         | That is certainly true - associative arrays in c++ (std::map)
         | for example, are implemented as red-black trees.
        
           | tgv wrote:
           | I think many devs don't know the difference and simply call
           | any dictionary/associative array a hash map. It might be one
           | of the concepts that "the internet" promotes: it sounds
           | fancy, more technical, makes you seem more knowledgeable, so
           | it gets repeated. Then newcomers think this is the way it's
           | always been called, and that gives it enough visibility to
           | become the preferred name.
        
             | nmz wrote:
             | Quite frankly I'd love a programmers dictionary over terms,
             | I recently called a file with a csv like format a db
             | because, well, its not a csv and I don't know what else to
             | call it.
        
         | meltyness wrote:
         | This seems pertinent, NEWS > bash-5.0 to bash-5.1 > mm
         | 
         | Seems to suggest it's indeed a hashmap in implementation, but I
         | can't be bothered to look any closer.
        
       | wwoessi wrote:
       | bashmaps?
        
       | DSpinellis wrote:
       | I advocate the following rules for when to write and when not to
       | write a shell script.
       | 
       | # Write a shell script:
       | 
       | * Heavy lifting done by powerful tool (sort, grep, curl, git,
       | sed, find, ...)
       | 
       | * Script will glue diverse tools
       | 
       | * Workflow resembles a pipeline
       | 
       | * Steps can be interactively developed as shell commands
       | 
       | * Portability
       | 
       | * Avoid dependency hell
       | 
       | * One-off job
       | 
       | # Avoid shell scripting:
       | 
       | * Difficult to see the preceding patterns
       | 
       | * Hot loops
       | 
       | * Complex arithmetic / data structures / parameters / error
       | handling
       | 
       | * Mostly binary data
       | 
       | * Large code body (> 500 LoC)
       | 
       | * Need a user interface
       | 
       | A need for associative arrays (implemented in Bash as via
       | hashmaps) moves the task to the second category (avoid shell
       | scripting).
        
         | nativeit wrote:
         | I've been a sysadmin for nearly a decade, a frontend web
         | designer for much longer (I still have a book on all the
         | exciting changes in HTML4), and while I can very easily learn,
         | compose, and use many markup and scripting languages, I have
         | always struggled with full-on programming languages, and I'm
         | not exactly sure why. Part of it, I think, is that most
         | tutorials and online learning resources are focused on novices
         | who don't have any existing grasp on general programming
         | concepts and syntax, but I'm already pretty deep into Bash. To
         | the extent that I am sure I have crossed the thresholds you
         | list, and used quite long and complex Bash scripts for tasks
         | that would almost certainly be easier in Python. I'd love to
         | find _A Bash Scripter's Guide To Python_ or something similar--
         | an intermediate course that assumes that I already know about
         | variables, operators, functions, Boolean expressions, et al. I
         | have searched for this a few times, but it's full of keywords
         | that makes searching Google difficult.
         | 
         | So this has inspired me to Ask HN, I'm getting ready to post it
         | with a reference to this discussion, but thought I'd start
         | here: does anyone know of a good resource for learning Python
         | (or Go, Perl...any good small project/scripting/solo hacking
         | languages) that's tailored for folks who already have a good
         | foundation in shell scripting, markup, config/infra automation,
         | build tools, etc.? I'm open to books, web-based tutorials,
         | apps, or just good examples for studying.
         | 
         | I'm open to the notion that I simply haven't put in the work,
         | and powered through the doldrums of novice tutorials far enough
         | to get to where the meaty stuff is. Worst case, I'm a big fan
         | of taking courses at the local community college for my own
         | edification, absent any specific degree program or professional
         | certification. It would still necessitate a lot of
         | remedial/redundant steps, but I can always help others through
         | those chapters while filling in any of my own gaps. Day-to-day,
         | I generally work alone, but I find such things are easier with
         | others to help motivate and focus my efforts. Perhaps I have
         | answered my own question, but even still, I appreciate any
         | advice/recommendations folks might have.
        
           | nativeit wrote:
           | My search through existing Ask HN has shown that this,
           | unsurprisingly, has been asked before by several people in
           | other specific contexts (side note, Ask HN is such an
           | incredibly useful resource, thanks to everyone who engages
           | with these questions). I don't want to add more noise, so I'm
           | going to work through the existing answers before posting.
           | 
           | If anyone else is interested, this thread from 2020 is where
           | I am starting, it seems to align with my own quest pretty
           | well: https://news.ycombinator.com/item?id=22932794
        
           | wellshapedwords wrote:
           | > assumes that I already know about variables, operators,
           | functions, Boolean expressions, et al.
           | 
           | Learning Go by Jon Bodner is a good choice. It seems to
           | assume that Go is the reader's second (or tenth) language.
        
           | brianpan wrote:
           | One of the differences between "general programming" and the
           | kinds of coding that you have done is the /approach/. I'm not
           | sure if that's even the right word, but there's a different
           | set of concerns that are important.
           | 
           | My guess is that you can easily learn the syntax and that you
           | have the logical and analytical skills, but the part you have
           | to learn is how to THINK about programming and how to DESIGN
           | a program. If you have or haven't taking coding classes, I
           | think reviewing topics like data structures, algorithms,
           | encapsulation/object oriented programming, functional
           | programming, etc. is the way to learn how to think about
           | general programming. I don't think the language matters, but
           | there might be resources about these topics in the language
           | you're interested in.
           | 
           | An example of what you DON'T want is something like Effective
           | Go (not just because it's out-of-date now):
           | https://go.dev/doc/effective_go. This page can give you a
           | really good base of information about what Go is, but I think
           | you'll get much more bang for your buck with a resource that
           | is more about the WHYs of programming rather than the WHATs.
        
         | kmstout wrote:
         | A couple things:
         | 
         | - Between using Bash's functions and breaking large scripts
         | into multiple, separate scripts, one can keep things reasonably
         | tidy. Also, functions and scripts can be combined in all the
         | ways (e.g., piping and process substition) that other programs
         | can.
         | 
         | - If I run into a case where Bash is a poor fit for a job, I
         | ask myself, "Self, what program would make this easy to do in a
         | shell script?" If I can respond with a good answer, I write
         | that, then continue with the shell scripting. If not, I write
         | in something else (what the kids would call a "proper"
         | language).
        
       | pie_flavor wrote:
       | I'm guilty of this. I knew zsh had them but since I can never
       | remember the exact things zsh has that bash doesn't, I just
       | assume anything remotely useful isn't compatible.
       | 
       | This policy comes from a six hour debugging session involving
       | (somewhere) a script that manipulated a binary file - bash can't
       | store zero bytes in variables and zsh can, but it's not like
       | it'll _tell_ you that it 's pointlessly truncating your data and
       | I never thought to look. So now every step in that script gets
       | converted back and forth through xxd, and I don't trust Bash
       | anymore.
        
       | rednafi wrote:
       | I discover stuff like this every day, and it's delightful. Sure,
       | reading the manual would've saved me from the surprise, but it's
       | incredibly difficult for me to read them unless I have a specific
       | goal in hand.
       | 
       | I found out about hashmaps in Bash a year ago[1], and it came as
       | a surprise. This morning, I came across dynamic shell variables
       | and the indirection syntax[2]. Each time I wrote about them and
       | learned more than I would have if I had just passively grokked
       | the manual.
       | 
       | [1]: https://rednafi.com/misc/associative_arrays_in_bash/
       | 
       | [2]: https://rednafi.com/misc/dynamic_shell_variables/
        
       | lervag wrote:
       | Notice that other shells also has associative arrays, or at least
       | zsh. I've found hyperpolyglot [0] to be a nice Rosetta stone for
       | translating syntax between e.g. bash and zsh.
       | 
       | [0]: https://hyperpolyglot.org/unix-shells#associative-arrays
        
       | nickjj wrote:
       | One thing the article doesn't mention is how you can use indirect
       | expansion to get a list of all keys.
       | 
       | For example: `${!myvar[@]}` would list all of the keys.
       | 
       | I've written about associative arrays in Bash a bit here:
       | https://nickjanetakis.com/blog/associative-arrays-in-bash-ak...
        
         | singularity2001 wrote:
         | doesn't work in zsh?
        
       | PeterWhittaker wrote:
       | bash associative arrays are fantastic, I've made heavy use of
       | them, but be warned that there have been several memory leaks in
       | the implementation. (Sorry, no version notes, once we realized
       | this, we rewrote a key component in C.)
       | 
       | IIRC, the latest bash addresses all of these, but that doesn't
       | help too much if you are stuck with an older, stable OS, e.g.,
       | RHEL 7 or 8; even 9 likely has a few remaining.
       | 
       | These leaks become an issue if you have a long running bash
       | script with frequent adds and updates. The update leak can be
       | mitigated somewhat by calling unset, e.g., unset a[b], before
       | updating, but only partially (again, apologies, no notes, just
       | the memory of the discovery and the need to drop bash).
       | 
       | I'd agree with the idea that bash wasn't the best choice for this
       | purpose in the first place, but there was history and other
       | technical debt involved.
        
       | oweiler wrote:
       | They are also slow AF because a lookup takes linear time.
        
         | Izkata wrote:
         | Which is because they're not hashmaps, they're associative
         | arrays. Article treats them as the same thing, but they're not
         | - that's why the "declare -A" is A and not H - it stands for
         | "associative".
        
           | xena wrote:
           | Author of the article here. As far as I care, if it quacks
           | like a hashmap, it's better to describe it as a hashmap. The
           | fact that it's an associative array under the hood is
           | irrelevant.
        
             | tremon wrote:
             | It doesn't; it's just that you probably never heard the
             | quack of a hashmap so you don't know the difference.
             | 
             | A hashmap is a very specific structure that uses a hashing
             | algorithm to normalize the key sizes, and then usually
             | constructs a tree-like structure for fast key lookups.
             | Anything that doesn't use such an implementation under the
             | hood should not be called a hashmap, whether you care or
             | not.
        
       | DiabloD3 wrote:
       | No one else seems to have mentioned this, but POSIX sh does not
       | include this feature.
       | 
       | Until it does, and major POSIX shs have shipped with it for a
       | decade, then the feature will actually exist in a way that the
       | average shell coder cares about. You're better off just shipping
       | Rust/Go/etc binaries and leave sh for your simple glue tasks.
       | 
       | Even I've eventually switched to this, and I've written 10k+ long
       | Bash scripts that followed best practices and passed shellcheck's
       | more paranoid optional tests.
       | 
       | Use the right language for the right job.
        
         | abathur wrote:
         | > then the feature will actually exist in a way that the
         | average shell coder cares about
         | 
         | I think it's worth picking at this a bit. At least IME, a
         | fairly small fraction of the Shell I write needs to run
         | literally (any|every)where.
         | 
         | I don't mean to suggest there aren't people/projects for whom
         | the opposite is true--just that it's worth chunking those cases
         | and thinking about them differently.
         | 
         | It obviously isn't a global solution, but in the Nix ecosystem
         | we have decent idioms for asserting control over the shell and
         | tools any given script runs with.
         | 
         | Reliable environment provisioning can spare hundreds of lines
         | of code real-world Shell tends to accumulate to sanity-check
         | the runtime environment and adapt to the presence/absence of
         | various utilities. It also enables us to use newer
         | shells/features (and shell libraries) with confidence.
         | 
         | It's enough leverage that I only give it up when I must.
        
         | nmz wrote:
         | POSIX sh doesn't even have arrays. I remember having to use awk
         | for that functionality.
        
       | nielsbot wrote:
       | Nice that these exist--but does anyone else absolutely abhor
       | shell programming? The syntax is impossible to memorize, it's
       | incredibly easy to make mistakes, and debugging is a pain. I hate
       | it more than C++ and AppleScript.
        
         | ryapric wrote:
         | I enjoy it quite a lot :shrug:
         | 
         | Bash itself isn't a very big language, so I wouldn't call it
         | "impossible to memorize".
        
         | irunmyownemail wrote:
         | I have around a billion short bash scripts, it's rare I've used
         | an array but it's cool it has it as long as the script doesn't
         | go beyond a few lines.
        
         | nmz wrote:
         | Have you tried plan9's rc? easy to memorize syntax thing. It's
         | still easy to make mistakes though and nobody uses it.
        
       | lars512 wrote:
       | Unfortunately, MacOS ships an earlier version of bash that does
       | not include associative arrays, so they're not as portable as you
       | might like.
        
       | syntacticbs wrote:
       | Oh dear. I've been trying to get people to not use this feature
       | for a while.
       | 
       | One thing that has bitten me in the past is that, if you declare
       | your associative arrays within a function, that associative array
       | is ALWAYS global. Even if you declare it with `local -A` it will
       | still be global. Despite that, you cannot pass an associative
       | array to a function by value. I say "by value" because while you
       | can't call `foo ${associative_array}` and pick it up in foo with
       | `local arg=$1, you can pass it "by reference" with `foo
       | associative_array` and pick it up in foo with `local -n arg=$1`,
       | but if you give the passed in dereferenced variable a name that
       | is already used in the global scope, it will blow up, eg `local
       | -n associative_array=$1`.
       | 
       | As a general rule for myself when writing bash, if I think one of
       | my colleagues who has an passable knowledge of bash will need to
       | get man pages out to figure out what my code is doing, the bash
       | foo is too strong and it needs to be dumbed down or re-written in
       | another language. Associative arrays almost always hit this bar.
        
         | jpavel2 wrote:
         | I'm not seeing this local scope leak with bash 5.2.15. The
         | below script works as I'd expect:                 #!/bin/bash
         | declare -A map1=([x]=2)       echo "1. Global scope map1[x]:
         | ${map1[x]}"              func1() {           echo " * Enter
         | func1"           local -A map1           map1[x]=3
         | echo "   Local scope map1[x]: ${map1[x]}"       }
         | func1              echo "2. Global scope map1[x]: ${map1[x]}"
         | 
         | outputting                 1. Global scope map1[x]: 2        *
         | Enter func1          Local scope map1[x]: 3       2. Global
         | scope map1[x]: 2
        
           | syntacticbs wrote:
           | The local scope leak seems to only happen when you drop down
           | the call stack. See below how I can call func2 from the top
           | level and it's fine, but if I call it from within func1, it
           | will leak.                 #!/bin/bash              declare
           | -A map1=([x]=2)       echo "1. Global scope map1[x]:
           | ${map1[x]}"       func1() {           echo " * Enter func1"
           | local -A map1           map1[x]=3           echo "   Local
           | scope map1[x]: ${map1[x]}"           func2       }
           | func2() {           echo "  * Enter func2"           echo "
           | Local scope map1[x]: ${map1[x]}"       }       func1
           | func2       echo "2. Global scope map1[x]: ${map1[x]}"
           | 
           | outputing: 1. Global scope map1[x]: 2 * Enter func1 Local
           | scope map1[x]: 3 * Enter func2 Local scope map1[x]: 3 * Enter
           | func2 Local scope map1[x]: 2 2. Global scope map1[x]: 2
           | 
           | UPDATE: I did a bit of exploration and it turns out ANY
           | variable declared `local` is in the scope of a function lower
           | down in the call stack. But if you declare a variable as
           | `local` in a called function that shadows the name of a
           | variable in a callee function, it will shadow the callee's
           | name and reset the variable back to the vallee's value when
           | the function returns. I have been writing bash for years and
           | did not realise this is the case. It is even described in the
           | man page: When local is used within a function, it causes the
           | variable name to have a visible scope restricted to that
           | function and its children.
           | 
           | Thank you. You have taught me two things today. One is a bash
           | feature I did not know existed. The second is a new reason to
           | avoid writing complex bash.
        
       | faragon wrote:
       | LZ77 compression/decompression in pure Bash using hashmaps:
       | 
       | https://github.com/faragon/lzb/blob/master/lzb
        
       | evgpbfhnr wrote:
       | Don't loop on values with `*`; the difference key/value is the
       | lack of `!` at the start of the expression; `*` and `@` rules are
       | the sames a $@ and $* and you almost never want *.
        
       | ssahoo wrote:
       | With that kind of syntax, Wouldn't you just use perl or python
       | instead?
        
       | bluedino wrote:
       | Got burned on this on an interview question before.
       | 
       | In a related question I said something about switching to a
       | language like Python when a script started to get "complicated"
       | 
       | Then the interviewer explained how his favorite language was
       | bash, how he uses it for everything...
       | 
       | I did not get the job. Ironically my next job I did a bunch of
       | Perl to Bash conversion.
        
       ___________________________________________________________________
       (page generated 2025-01-11 23:01 UTC)