mirror of
https://github.com/flokoe/bash-hackers-wiki.git
synced 2024-11-25 07:43:42 +01:00
206 lines
81 KiB
HTML
206 lines
81 KiB
HTML
<!doctype html><html lang=en class=no-js> <head><meta charset=utf-8><meta name=viewport content="width=device-width,initial-scale=1"><link href=https://flokoe.github.io/bash-hackers-wiki/syntax/arrays/ rel=canonical><link href=../arith_expr/ rel=prev><link href=../basicgrammar/ rel=next><link rel=icon href=../../assets/images/favicon.png><meta name=generator content="mkdocs-1.6.1, mkdocs-material-9.5.44"><title>Arrays - The Bash Hackers Wiki</title><link rel=stylesheet href=../../assets/stylesheets/main.0253249f.min.css><link rel=stylesheet href=../../assets/stylesheets/palette.06af60db.min.css><link rel=preconnect href=https://fonts.gstatic.com crossorigin><link rel=stylesheet href="https://fonts.googleapis.com/css?family=Roboto:300,300i,400,400i,700,700i%7CRoboto+Mono:400,400i,700,700i&display=fallback"><style>:root{--md-text-font:"Roboto";--md-code-font:"Roboto Mono"}</style><script>__md_scope=new URL("../..",location),__md_hash=e=>[...e].reduce(((e,_)=>(e<<5)-e+_.charCodeAt(0)),0),__md_get=(e,_=localStorage,t=__md_scope)=>JSON.parse(_.getItem(t.pathname+"."+e)),__md_set=(e,_,t=localStorage,a=__md_scope)=>{try{t.setItem(a.pathname+"."+e,JSON.stringify(_))}catch(e){}}</script></head> <body dir=ltr data-md-color-scheme=default data-md-color-primary=indigo data-md-color-accent=indigo> <input class=md-toggle data-md-toggle=drawer type=checkbox id=__drawer autocomplete=off> <input class=md-toggle data-md-toggle=search type=checkbox id=__search autocomplete=off> <label class=md-overlay for=__drawer></label> <div data-md-component=skip> <a href=#arrays class=md-skip> Skip to content </a> </div> <div data-md-component=announce> </div> <header class=md-header data-md-component=header> <nav class="md-header__inner md-grid" aria-label=Header> <a href=../.. title="The Bash Hackers Wiki" class="md-header__button md-logo" aria-label="The Bash Hackers Wiki" data-md-component=logo> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 24 24"><path d="M12 8a3 3 0 0 0 3-3 3 3 0 0 0-3-3 3 3 0 0 0-3 3 3 3 0 0 0 3 3m0 3.54C9.64 9.35 6.5 8 3 8v11c3.5 0 6.64 1.35 9 3.54 2.36-2.19 5.5-3.54 9-3.54V8c-3.5 0-6.64 1.35-9 3.54"/></svg> </a> <label class="md-header__button md-icon" for=__drawer> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 24 24"><path d="M3 6h18v2H3zm0 5h18v2H3zm0 5h18v2H3z"/></svg> </label> <div class=md-header__title data-md-component=header-title> <div class=md-header__ellipsis> <div class=md-header__topic> <span class=md-ellipsis> The Bash Hackers Wiki </span> </div> <div class=md-header__topic data-md-component=header-topic> <span class=md-ellipsis> Arrays </span> </div> </div> </div> <form class=md-header__option data-md-component=palette> <input class=md-option data-md-color-media data-md-color-scheme=default data-md-color-primary=indigo data-md-color-accent=indigo aria-label="Switch to dark mode" type=radio name=__palette id=__palette_0> <label class="md-header__button md-icon" title="Switch to dark mode" for=__palette_1 hidden> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 24 24"><path d="M12 8a4 4 0 0 0-4 4 4 4 0 0 0 4 4 4 4 0 0 0 4-4 4 4 0 0 0-4-4m0 10a6 6 0 0 1-6-6 6 6 0 0 1 6-6 6 6 0 0 1 6 6 6 6 0 0 1-6 6m8-9.31V4h-4.69L12 .69 8.69 4H4v4.69L.69 12 4 15.31V20h4.69L12 23.31 15.31 20H20v-4.69L23.31 12z"/></svg> </label> <input class=md-option data-md-color-media data-md-color-scheme=slate data-md-color-primary=indigo data-md-color-accent=indigo aria-label="Switch to light mode" type=radio name=__palette id=__palette_1> <label class="md-header__button md-icon" title="Switch to light mode" for=__palette_0 hidden> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 24 24"><path d="M12 18c-.89 0-1.74-.2-2.5-.55C11.56 16.5 13 14.42 13 12s-1.44-4.5-3.5-5.45C10.26 6.2 11.11 6 12 6a6 6 0 0 1 6 6 6 6 0 0 1-6 6m8-9.31V4h-4.69L12 .69 8.69 4H4v4.69L.69 12 4 15.31V20h4.69L12 23.31 15.31 20H20v-4.69L23.31 12z"/></svg> </label> </form> <script>var palette=__md_get("__palette");if(palette&&palette.color){if("(prefers-color-scheme)"===palette.color.media){var media=matchMedia("(prefers-color-scheme: light)"),input=document.querySelector(media.matches?"[data-md-color-media='(prefers-color-scheme: light)']":"[data-md-color-media='(prefers-color-scheme: dark)']");palette.color.media=input.getAttribute("data-md-color-media"),palette.color.scheme=input.getAttribute("data-md-color-scheme"),palette.color.primary=input.getAttribute("data-md-color-primary"),palette.color.accent=input.getAttribute("data-md-color-accent")}for(var[key,value]of Object.entries(palette.color))document.body.setAttribute("data-md-color-"+key,value)}</script> <label class="md-header__button md-icon" for=__search> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 24 24"><path d="M9.5 3A6.5 6.5 0 0 1 16 9.5c0 1.61-.59 3.09-1.56 4.23l.27.27h.79l5 5-1.5 1.5-5-5v-.79l-.27-.27A6.52 6.52 0 0 1 9.5 16 6.5 6.5 0 0 1 3 9.5 6.5 6.5 0 0 1 9.5 3m0 2C7 5 5 7 5 9.5S7 14 9.5 14 14 12 14 9.5 12 5 9.5 5"/></svg> </label> <div class=md-search data-md-component=search role=dialog> <label class=md-search__overlay for=__search></label> <div class=md-search__inner role=search> <form class=md-search__form name=search> <input type=text class=md-search__input name=query aria-label=Search placeholder=Search autocapitalize=off autocorrect=off autocomplete=off spellcheck=false data-md-component=search-query required> <label class="md-search__icon md-icon" for=__search> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 24 24"><path d="M9.5 3A6.5 6.5 0 0 1 16 9.5c0 1.61-.59 3.09-1.56 4.23l.27.27h.79l5 5-1.5 1.5-5-5v-.79l-.27-.27A6.52 6.52 0 0 1 9.5 16 6.5 6.5 0 0 1 3 9.5 6.5 6.5 0 0 1 9.5 3m0 2C7 5 5 7 5 9.5S7 14 9.5 14 14 12 14 9.5 12 5 9.5 5"/></svg> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 24 24"><path d="M20 11v2H8l5.5 5.5-1.42 1.42L4.16 12l7.92-7.92L13.5 5.5 8 11z"/></svg> </label> <nav class=md-search__options aria-label=Search> <button type=reset class="md-search__icon md-icon" title=Clear aria-label=Clear tabindex=-1> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 24 24"><path d="M19 6.41 17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"/></svg> </button> </nav> <div class=md-search__suggest data-md-component=search-suggest></div> </form> <div class=md-search__output> <div class=md-search__scrollwrap tabindex=0 data-md-scrollfix> <div class=md-search-result data-md-component=search-result> <div class=md-search-result__meta> Initializing search </div> <ol class=md-search-result__list role=presentation></ol> </div> </div> </div> </div> </div> <div class=md-header__source> <a href=https://github.com/flokoe/bash-hackers-wiki title="Go to repository" class=md-source data-md-component=source> <div class="md-source__icon md-icon"> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 496 512"><!-- Font Awesome Free 6.6.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2024 Fonticons, Inc.--><path d="M165.9 397.4c0 2-2.3 3.6-5.2 3.6-3.3.3-5.6-1.3-5.6-3.6 0-2 2.3-3.6 5.2-3.6 3-.3 5.6 1.3 5.6 3.6m-31.1-4.5c-.7 2 1.3 4.3 4.3 4.9 2.6 1 5.6 0 6.2-2s-1.3-4.3-4.3-5.2c-2.6-.7-5.5.3-6.2 2.3m44.2-1.7c-2.9.7-4.9 2.6-4.6 4.9.3 2 2.9 3.3 5.9 2.6 2.9-.7 4.9-2.6 4.6-4.6-.3-1.9-3-3.2-5.9-2.9M244.8 8C106.1 8 0 113.3 0 252c0 110.9 69.8 205.8 169.5 239.2 12.8 2.3 17.3-5.6 17.3-12.1 0-6.2-.3-40.4-.3-61.4 0 0-70 15-84.7-29.8 0 0-11.4-29.1-27.8-36.6 0 0-22.9-15.7 1.6-15.4 0 0 24.9 2 38.6 25.8 21.9 38.6 58.6 27.5 72.9 20.9 2.3-16 8.8-27.1 16-33.7-55.9-6.2-112.3-14.3-112.3-110.5 0-27.5 7.6-41.3 23.6-58.9-2.6-6.5-11.1-33.3 2.6-67.9 20.9-6.5 69 27 69 27 20-5.6 41.5-8.5 62.8-8.5s42.8 2.9 62.8 8.5c0 0 48.1-33.6 69-27 13.7 34.7 5.2 61.4 2.6 67.9 16 17.7 25.8 31.5 25.8 58.9 0 96.5-58.9 104.2-114.8 110.5 9.2 7.9 17 22.9 17 46.4 0 33.7-.3 75.4-.3 83.6 0 6.5 4.6 14.4 17.3 12.1C428.2 457.8 496 362.9 496 252 496 113.3 383.5 8 244.8 8M97.2 352.9c-1.3 1-1 3.3.7 5.2 1.6 1.6 3.9 2.3 5.2 1 1.3-1 1-3.3-.7-5.2-1.6-1.6-3.9-2.3-5.2-1m-10.8-8.1c-.7 1.3.3 2.9 2.3 3.9 1.6 1 3.6.7 4.3-.7.7-1.3-.3-2.9-2.3-3.9-2-.6-3.6-.3-4.3.7m32.4 35.6c-1.6 1.3-1 4.3 1.3 6.2 2.3 2.3 5.2 2.6 6.5 1 1.3-1.3.7-4.3-1.3-6.2-2.2-2.3-5.2-2.6-6.5-1m-11.4-14.7c-1.6 1-1.6 3.6 0 5.9s4.3 3.3 5.6 2.3c1.6-1.3 1.6-3.9 0-6.2-1.4-2.3-4-3.3-5.6-2"/></svg> </div> <div class=md-source__repository> flokoe/bash-hackers-wiki </div> </a> </div> </nav> </header> <div class=md-container data-md-component=container> <nav class=md-tabs aria-label=Tabs data-md-component=tabs> <div class=md-grid> <ul class=md-tabs__list> <li class=md-tabs__item> <a href=../.. class=md-tabs__link> Start </a> </li> <li class=md-tabs__item> <a href=../../commands/classictest/ class=md-tabs__link> Commands </a> </li> <li class=md-tabs__item> <a href=../../dict/directory/ class=md-tabs__link> Dict </a> </li> <li class=md-tabs__item> <a href=../../howto/calculate-dc/ class=md-tabs__link> Howto </a> </li> <li class=md-tabs__item> <a href=../../internals/shell_options/ class=md-tabs__link> Internals </a> </li> <li class=md-tabs__item> <a href=../../misc/bashphorisms/ class=md-tabs__link> Misc </a> </li> <li class=md-tabs__item> <a href=../../scripting/bashbehaviour/ class=md-tabs__link> Scripting </a> </li> <li class=md-tabs__item> <a href=../../snipplets/ class=md-tabs__link> Snipplets </a> </li> <li class="md-tabs__item md-tabs__item--active"> <a href=../arith_expr/ class=md-tabs__link> Syntax </a> </li> <li class=md-tabs__item> <a href=../../tags/ class=md-tabs__link> Tags </a> </li> </ul> </div> </nav> <main class=md-main data-md-component=main> <div class="md-main__inner md-grid"> <div class="md-sidebar md-sidebar--primary" data-md-component=sidebar data-md-type=navigation> <div class=md-sidebar__scrollwrap> <div class=md-sidebar__inner> <nav class="md-nav md-nav--primary md-nav--lifted" aria-label=Navigation data-md-level=0> <label class=md-nav__title for=__drawer> <a href=../.. title="The Bash Hackers Wiki" class="md-nav__button md-logo" aria-label="The Bash Hackers Wiki" data-md-component=logo> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 24 24"><path d="M12 8a3 3 0 0 0 3-3 3 3 0 0 0-3-3 3 3 0 0 0-3 3 3 3 0 0 0 3 3m0 3.54C9.64 9.35 6.5 8 3 8v11c3.5 0 6.64 1.35 9 3.54 2.36-2.19 5.5-3.54 9-3.54V8c-3.5 0-6.64 1.35-9 3.54"/></svg> </a> The Bash Hackers Wiki </label> <div class=md-nav__source> <a href=https://github.com/flokoe/bash-hackers-wiki title="Go to repository" class=md-source data-md-component=source> <div class="md-source__icon md-icon"> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 496 512"><!-- Font Awesome Free 6.6.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2024 Fonticons, Inc.--><path d="M165.9 397.4c0 2-2.3 3.6-5.2 3.6-3.3.3-5.6-1.3-5.6-3.6 0-2 2.3-3.6 5.2-3.6 3-.3 5.6 1.3 5.6 3.6m-31.1-4.5c-.7 2 1.3 4.3 4.3 4.9 2.6 1 5.6 0 6.2-2s-1.3-4.3-4.3-5.2c-2.6-.7-5.5.3-6.2 2.3m44.2-1.7c-2.9.7-4.9 2.6-4.6 4.9.3 2 2.9 3.3 5.9 2.6 2.9-.7 4.9-2.6 4.6-4.6-.3-1.9-3-3.2-5.9-2.9M244.8 8C106.1 8 0 113.3 0 252c0 110.9 69.8 205.8 169.5 239.2 12.8 2.3 17.3-5.6 17.3-12.1 0-6.2-.3-40.4-.3-61.4 0 0-70 15-84.7-29.8 0 0-11.4-29.1-27.8-36.6 0 0-22.9-15.7 1.6-15.4 0 0 24.9 2 38.6 25.8 21.9 38.6 58.6 27.5 72.9 20.9 2.3-16 8.8-27.1 16-33.7-55.9-6.2-112.3-14.3-112.3-110.5 0-27.5 7.6-41.3 23.6-58.9-2.6-6.5-11.1-33.3 2.6-67.9 20.9-6.5 69 27 69 27 20-5.6 41.5-8.5 62.8-8.5s42.8 2.9 62.8 8.5c0 0 48.1-33.6 69-27 13.7 34.7 5.2 61.4 2.6 67.9 16 17.7 25.8 31.5 25.8 58.9 0 96.5-58.9 104.2-114.8 110.5 9.2 7.9 17 22.9 17 46.4 0 33.7-.3 75.4-.3 83.6 0 6.5 4.6 14.4 17.3 12.1C428.2 457.8 496 362.9 496 252 496 113.3 383.5 8 244.8 8M97.2 352.9c-1.3 1-1 3.3.7 5.2 1.6 1.6 3.9 2.3 5.2 1 1.3-1 1-3.3-.7-5.2-1.6-1.6-3.9-2.3-5.2-1m-10.8-8.1c-.7 1.3.3 2.9 2.3 3.9 1.6 1 3.6.7 4.3-.7.7-1.3-.3-2.9-2.3-3.9-2-.6-3.6-.3-4.3.7m32.4 35.6c-1.6 1.3-1 4.3 1.3 6.2 2.3 2.3 5.2 2.6 6.5 1 1.3-1.3.7-4.3-1.3-6.2-2.2-2.3-5.2-2.6-6.5-1m-11.4-14.7c-1.6 1-1.6 3.6 0 5.9s4.3 3.3 5.6 2.3c1.6-1.3 1.6-3.9 0-6.2-1.4-2.3-4-3.3-5.6-2"/></svg> </div> <div class=md-source__repository> flokoe/bash-hackers-wiki </div> </a> </div> <ul class=md-nav__list data-md-scrollfix> <li class=md-nav__item> <a href=../.. class=md-nav__link> <span class=md-ellipsis> Start </span> </a> </li> <li class="md-nav__item md-nav__item--nested"> <input class="md-nav__toggle md-toggle " type=checkbox id=__nav_2> <label class=md-nav__link for=__nav_2 id=__nav_2_label tabindex=0> <span class=md-ellipsis> Commands </span> <span class="md-nav__icon md-icon"></span> </label> <nav class=md-nav data-md-level=1 aria-labelledby=__nav_2_label aria-expanded=false> <label class=md-nav__title for=__nav_2> <span class="md-nav__icon md-icon"></span> Commands </label> <ul class=md-nav__list data-md-scrollfix> <li class=md-nav__item> <a href=../../commands/classictest/ class=md-nav__link> <span class=md-ellipsis> The classic test command </span> </a> </li> <li class="md-nav__item md-nav__item--nested"> <input class="md-nav__toggle md-toggle " type=checkbox id=__nav_2_2> <label class=md-nav__link for=__nav_2_2 id=__nav_2_2_label tabindex=0> <span class=md-ellipsis> Builtin </span> <span class="md-nav__icon md-icon"></span> </label> <nav class=md-nav data-md-level=2 aria-labelledby=__nav_2_2_label aria-expanded=false> <label class=md-nav__title for=__nav_2_2> <span class="md-nav__icon md-icon"></span> Builtin </label> <ul class=md-nav__list data-md-scrollfix> <li class=md-nav__item> <a href=../../commands/builtin/caller/ class=md-nav__link> <span class=md-ellipsis> The caller builtin command </span> </a> </li> <li class=md-nav__item> <a href=../../commands/builtin/cd/ class=md-nav__link> <span class=md-ellipsis> The cd builtin command </span> </a> </li> <li class=md-nav__item> <a href=../../commands/builtin/declare/ class=md-nav__link> <span class=md-ellipsis> The declare builtin command </span> </a> </li> <li class=md-nav__item> <a href=../../commands/builtin/echo/ class=md-nav__link> <span class=md-ellipsis> The echo builtin command </span> </a> </li> <li class=md-nav__item> <a href=../../commands/builtin/eval/ class=md-nav__link> <span class=md-ellipsis> The eval builtin command </span> </a> </li> <li class=md-nav__item> <a href=../../commands/builtin/exec/ class=md-nav__link> <span class=md-ellipsis> The exec builtin command </span> </a> </li> <li class=md-nav__item> <a href=../../commands/builtin/exit/ class=md-nav__link> <span class=md-ellipsis> The exit builtin command </span> </a> </li> <li class=md-nav__item> <a href=../../commands/builtin/export/ class=md-nav__link> <span class=md-ellipsis> The export builtin command </span> </a> </li> <li class=md-nav__item> <a href=../../commands/builtin/kill/ class=md-nav__link> <span class=md-ellipsis> The kill builtin command </span> </a> </li> <li class=md-nav__item> <a href=../../commands/builtin/let/ class=md-nav__link> <span class=md-ellipsis> The let builtin command </span> </a> </li> <li class=md-nav__item> <a href=../../commands/builtin/local/ class=md-nav__link> <span class=md-ellipsis> The local builtin command </span> </a> </li> <li class=md-nav__item> <a href=../../commands/builtin/mapfile/ class=md-nav__link> <span class=md-ellipsis> The mapfile builtin command </span> </a> </li> <li class=md-nav__item> <a href=../../commands/builtin/printf/ class=md-nav__link> <span class=md-ellipsis> The printf command </span> </a> </li> <li class=md-nav__item> <a href=../../commands/builtin/read/ class=md-nav__link> <span class=md-ellipsis> The read builtin command </span> </a> </li> <li class=md-nav__item> <a href=../../commands/builtin/readonly/ class=md-nav__link> <span class=md-ellipsis> The readonly builtin command </span> </a> </li> <li class=md-nav__item> <a href=../../commands/builtin/return/ class=md-nav__link> <span class=md-ellipsis> The return builtin command </span> </a> </li> <li class=md-nav__item> <a href=../../commands/builtin/set/ class=md-nav__link> <span class=md-ellipsis> The set builtin command </span> </a> </li> <li class=md-nav__item> <a href=../../commands/builtin/shift/ class=md-nav__link> <span class=md-ellipsis> The shift builtin command </span> </a> </li> <li class=md-nav__item> <a href=../../commands/builtin/shopt/ class=md-nav__link> <span class=md-ellipsis> The shopt builtin command </span> </a> </li> <li class=md-nav__item> <a href=../../commands/builtin/trap/ class=md-nav__link> <span class=md-ellipsis> The trap builtin command </span> </a> </li> <li class=md-nav__item> <a href=../../commands/builtin/unset/ class=md-nav__link> <span class=md-ellipsis> The unset builtin command </span> </a> </li> <li class=md-nav__item> <a href=../../commands/builtin/wait/ class=md-nav__link> <span class=md-ellipsis> The wait builtin command </span> </a> </li> </ul> </nav> </li> </ul> </nav> </li> <li class="md-nav__item md-nav__item--nested"> <input class="md-nav__toggle md-toggle " type=checkbox id=__nav_3> <label class=md-nav__link for=__nav_3 id=__nav_3_label tabindex=0> <span class=md-ellipsis> Dict </span> <span class="md-nav__icon md-icon"></span> </label> <nav class=md-nav data-md-level=1 aria-labelledby=__nav_3_label aria-expanded=false> <label class=md-nav__title for=__nav_3> <span class="md-nav__icon md-icon"></span> Dict </label> <ul class=md-nav__list data-md-scrollfix> <li class=md-nav__item> <a href=../../dict/directory/ class=md-nav__link> <span class=md-ellipsis> Directory </span> </a> </li> <li class=md-nav__item> <a href=../../dict/end_of_options/ class=md-nav__link> <span class=md-ellipsis> End of Options </span> </a> </li> <li class=md-nav__item> <a href=../../dict/exit_status/ class=md-nav__link> <span class=md-ellipsis> Exit Status </span> </a> </li> <li class=md-nav__item> <a href=../../dict/file/ class=md-nav__link> <span class=md-ellipsis> File </span> </a> </li> <li class=md-nav__item> <a href=../../dict/filetimes/ class=md-nav__link> <span class=md-ellipsis> File timestamp </span> </a> </li> <li class=md-nav__item> <a href=../../dict/globbing/ class=md-nav__link> <span class=md-ellipsis> Globbing </span> </a> </li> <li class=md-nav__item> <a href=../../dict/hardlink/ class=md-nav__link> <span class=md-ellipsis> Hardlink </span> </a> </li> <li class=md-nav__item> <a href=../../dict/interpreter_directive/ class=md-nav__link> <span class=md-ellipsis> Interpreter Directive </span> </a> </li> <li class=md-nav__item> <a href=../../dict/parameter/ class=md-nav__link> <span class=md-ellipsis> Parameter </span> </a> </li> <li class=md-nav__item> <a href=../../dict/posix/ class=md-nav__link> <span class=md-ellipsis> POSIX </span> </a> </li> <li class=md-nav__item> <a href=../../dict/shell/ class=md-nav__link> <span class=md-ellipsis> Shell </span> </a> </li> <li class=md-nav__item> <a href=../../dict/special_file/ class=md-nav__link> <span class=md-ellipsis> Special file </span> </a> </li> <li class=md-nav__item> <a href=../../dict/symlink/ class=md-nav__link> <span class=md-ellipsis> Symlink </span> </a> </li> </ul> </nav> </li> <li class="md-nav__item md-nav__item--nested"> <input class="md-nav__toggle md-toggle " type=checkbox id=__nav_4> <label class=md-nav__link for=__nav_4 id=__nav_4_label tabindex=0> <span class=md-ellipsis> Howto </span> <span class="md-nav__icon md-icon"></span> </label> <nav class=md-nav data-md-level=1 aria-labelledby=__nav_4_label aria-expanded=false> <label class=md-nav__title for=__nav_4> <span class="md-nav__icon md-icon"></span> Howto </label> <ul class=md-nav__list data-md-scrollfix> <li class=md-nav__item> <a href=../../howto/calculate-dc/ class=md-nav__link> <span class=md-ellipsis> Calculating with dc </span> </a> </li> <li class=md-nav__item> <a href=../../howto/collapsing_functions/ class=md-nav__link> <span class=md-ellipsis> Collapsing Functions </span> </a> </li> <li class=md-nav__item> <a href=../../howto/conffile/ class=md-nav__link> <span class=md-ellipsis> Config files for your script </span> </a> </li> <li class=md-nav__item> <a href=../../howto/dissectabadoneliner/ class=md-nav__link> <span class=md-ellipsis> Dissect a bad oneliner </span> </a> </li> <li class=md-nav__item> <a href=../../howto/edit-ed/ class=md-nav__link> <span class=md-ellipsis> Editing files via scripts with ed </span> </a> </li> <li class=md-nav__item> <a href=../../howto/getopts_tutorial/ class=md-nav__link> <span class=md-ellipsis> Small getopts tutorial </span> </a> </li> <li class=md-nav__item> <a href=../../howto/mutex/ class=md-nav__link> <span class=md-ellipsis> Lock your script (against parallel execution) </span> </a> </li> <li class=md-nav__item> <a href=../../howto/pax/ class=md-nav__link> <span class=md-ellipsis> pax - the POSIX archiver </span> </a> </li> <li class=md-nav__item> <a href=../../howto/redirection_tutorial/ class=md-nav__link> <span class=md-ellipsis> Illustrated Redirection Tutorial </span> </a> </li> <li class=md-nav__item> <a href=../../howto/testing-your-scripts/ class=md-nav__link> <span class=md-ellipsis> Testing your scripts </span> </a> </li> </ul> </nav> </li> <li class="md-nav__item md-nav__item--nested"> <input class="md-nav__toggle md-toggle " type=checkbox id=__nav_5> <label class=md-nav__link for=__nav_5 id=__nav_5_label tabindex=0> <span class=md-ellipsis> Internals </span> <span class="md-nav__icon md-icon"></span> </label> <nav class=md-nav data-md-level=1 aria-labelledby=__nav_5_label aria-expanded=false> <label class=md-nav__title for=__nav_5> <span class="md-nav__icon md-icon"></span> Internals </label> <ul class=md-nav__list data-md-scrollfix> <li class=md-nav__item> <a href=../../internals/shell_options/ class=md-nav__link> <span class=md-ellipsis> List of shell options </span> </a> </li> </ul> </nav> </li> <li class="md-nav__item md-nav__item--nested"> <input class="md-nav__toggle md-toggle " type=checkbox id=__nav_6> <label class=md-nav__link for=__nav_6 id=__nav_6_label tabindex=0> <span class=md-ellipsis> Misc </span> <span class="md-nav__icon md-icon"></span> </label> <nav class=md-nav data-md-level=1 aria-labelledby=__nav_6_label aria-expanded=false> <label class=md-nav__title for=__nav_6> <span class="md-nav__icon md-icon"></span> Misc </label> <ul class=md-nav__list data-md-scrollfix> <li class=md-nav__item> <a href=../../misc/bashphorisms/ class=md-nav__link> <span class=md-ellipsis> The Bashphorisms </span> </a> </li> <li class=md-nav__item> <a href=../../misc/readthesourceluke/ class=md-nav__link> <span class=md-ellipsis> Readthesourceluke </span> </a> </li> <li class=md-nav__item> <a href=../../misc/shell_humor/ class=md-nav__link> <span class=md-ellipsis> Shell Humor </span> </a> </li> </ul> </nav> </li> <li class="md-nav__item md-nav__item--nested"> <input class="md-nav__toggle md-toggle " type=checkbox id=__nav_7> <label class=md-nav__link for=__nav_7 id=__nav_7_label tabindex=0> <span class=md-ellipsis> Scripting </span> <span class="md-nav__icon md-icon"></span> </label> <nav class=md-nav data-md-level=1 aria-labelledby=__nav_7_label aria-expanded=false> <label class=md-nav__title for=__nav_7> <span class="md-nav__icon md-icon"></span> Scripting </label> <ul class=md-nav__list data-md-scrollfix> <li class=md-nav__item> <a href=../../scripting/bashbehaviour/ class=md-nav__link> <span class=md-ellipsis> Bash's behaviour </span> </a> </li> <li class=md-nav__item> <a href=../../scripting/bashchanges/ class=md-nav__link> <span class=md-ellipsis> Bash changes </span> </a> </li> <li class=md-nav__item> <a href=../../scripting/basics/ class=md-nav__link> <span class=md-ellipsis> The basics of shell scripting </span> </a> </li> <li class=md-nav__item> <a href=../../scripting/debuggingtips/ class=md-nav__link> <span class=md-ellipsis> Debugging a script </span> </a> </li> <li class=md-nav__item> <a href=../../scripting/newbie_traps/ class=md-nav__link> <span class=md-ellipsis> Beginner Mistakes </span> </a> </li> <li class=md-nav__item> <a href=../../scripting/nonportable/ class=md-nav__link> <span class=md-ellipsis> Portability talk </span> </a> </li> <li class=md-nav__item> <a href=../../scripting/obsolete/ class=md-nav__link> <span class=md-ellipsis> Obsolete and deprecated syntax </span> </a> </li> <li class=md-nav__item> <a href=../../scripting/posparams/ class=md-nav__link> <span class=md-ellipsis> Handling positional parameters </span> </a> </li> <li class=md-nav__item> <a href=../../scripting/processtree/ class=md-nav__link> <span class=md-ellipsis> Bash and the process tree </span> </a> </li> <li class=md-nav__item> <a href=../../scripting/style/ class=md-nav__link> <span class=md-ellipsis> Scripting with style </span> </a> </li> <li class=md-nav__item> <a href=../../scripting/terminalcodes/ class=md-nav__link> <span class=md-ellipsis> Terminal codes (ANSI/VT100) introduction </span> </a> </li> </ul> </nav> </li> <li class="md-nav__item md-nav__item--nested"> <input class="md-nav__toggle md-toggle " type=checkbox id=__nav_8> <label class=md-nav__link for=__nav_8 id=__nav_8_label tabindex=0> <span class=md-ellipsis> Snipplets </span> <span class="md-nav__icon md-icon"></span> </label> <nav class=md-nav data-md-level=1 aria-labelledby=__nav_8_label aria-expanded=false> <label class=md-nav__title for=__nav_8> <span class="md-nav__icon md-icon"></span> Snipplets </label> <ul class=md-nav__list data-md-scrollfix> <li class=md-nav__item> <a href=../../snipplets/ class=md-nav__link> <span class=md-ellipsis> Small code snipplets </span> </a> </li> <li class=md-nav__item> <a href=../../snipplets/add_color_to_your_scripts/ class=md-nav__link> <span class=md-ellipsis> Add Color to your scripts </span> </a> </li> <li class=md-nav__item> <a href=../../snipplets/awkcsv/ class=md-nav__link> <span class=md-ellipsis> Using awk to deal with CSV that uses quoted/unquoted delimiters </span> </a> </li> <li class=md-nav__item> <a href=../../snipplets/filesize/ class=md-nav__link> <span class=md-ellipsis> Show size of a file </span> </a> </li> <li class=md-nav__item> <a href=../../snipplets/kill_bg_job_without_message/ class=md-nav__link> <span class=md-ellipsis> Kill a background job without a message </span> </a> </li> <li class=md-nav__item> <a href=../../snipplets/largestfile/ class=md-nav__link> <span class=md-ellipsis> Get largest file </span> </a> </li> <li class=md-nav__item> <a href=../../snipplets/pause_command/ class=md-nav__link> <span class=md-ellipsis> Pausing a script (like MSDOS pause command) </span> </a> </li> <li class=md-nav__item> <a href=../../snipplets/prargs/ class=md-nav__link> <span class=md-ellipsis> Print argument list for testing </span> </a> </li> <li class=md-nav__item> <a href=../../snipplets/print_horizontal_line/ class=md-nav__link> <span class=md-ellipsis> Print a horizontal line </span> </a> </li> <li class=md-nav__item> <a href=../../snipplets/rndstr/ class=md-nav__link> <span class=md-ellipsis> Print a random string or select random elements </span> </a> </li> <li class=md-nav__item> <a href=../../snipplets/screen_saverestore/ class=md-nav__link> <span class=md-ellipsis> Save and restore terminal/screen content </span> </a> </li> <li class=md-nav__item> <a href=../../snipplets/ssh_fetchkeys/ class=md-nav__link> <span class=md-ellipsis> Fetching SSH hostkeys without interaction </span> </a> </li> <li class=md-nav__item> <a href=../../snipplets/ssh_local_var/ class=md-nav__link> <span class=md-ellipsis> Run some bash commands with SSH remotely using local variables </span> </a> </li> <li class=md-nav__item> <a href=../../snipplets/wrapperargs/ class=md-nav__link> <span class=md-ellipsis> Generate code with own arguments properly quoted </span> </a> </li> <li class=md-nav__item> <a href=../../snipplets/xclip/ class=md-nav__link> <span class=md-ellipsis> X-Clipboard on Commandline </span> </a> </li> </ul> </nav> </li> <li class="md-nav__item md-nav__item--active md-nav__item--section md-nav__item--nested"> <input class="md-nav__toggle md-toggle " type=checkbox id=__nav_9 checked> <label class=md-nav__link for=__nav_9 id=__nav_9_label tabindex> <span class=md-ellipsis> Syntax </span> <span class="md-nav__icon md-icon"></span> </label> <nav class=md-nav data-md-level=1 aria-labelledby=__nav_9_label aria-expanded=true> <label class=md-nav__title for=__nav_9> <span class="md-nav__icon md-icon"></span> Syntax </label> <ul class=md-nav__list data-md-scrollfix> <li class=md-nav__item> <a href=../arith_expr/ class=md-nav__link> <span class=md-ellipsis> Arithmetic expressions </span> </a> </li> <li class="md-nav__item md-nav__item--active"> <input class="md-nav__toggle md-toggle" type=checkbox id=__toc> <label class="md-nav__link md-nav__link--active" for=__toc> <span class=md-ellipsis> Arrays </span> <span class="md-nav__icon md-icon"></span> </label> <a href=./ class="md-nav__link md-nav__link--active"> <span class=md-ellipsis> Arrays </span> </a> <nav class="md-nav md-nav--secondary" aria-label="Table of contents"> <label class=md-nav__title for=__toc> <span class="md-nav__icon md-icon"></span> Table of contents </label> <ul class=md-nav__list data-md-component=toc data-md-scrollfix> <li class=md-nav__item> <a href=#purpose class=md-nav__link> <span class=md-ellipsis> Purpose </span> </a> </li> <li class=md-nav__item> <a href=#indexing class=md-nav__link> <span class=md-ellipsis> Indexing </span> </a> </li> <li class=md-nav__item> <a href=#syntax class=md-nav__link> <span class=md-ellipsis> Syntax </span> </a> <nav class=md-nav aria-label=Syntax> <ul class=md-nav__list> <li class=md-nav__item> <a href=#referencing class=md-nav__link> <span class=md-ellipsis> Referencing </span> </a> </li> <li class=md-nav__item> <a href=#declaration class=md-nav__link> <span class=md-ellipsis> Declaration </span> </a> </li> <li class=md-nav__item> <a href=#storing-values class=md-nav__link> <span class=md-ellipsis> Storing values </span> </a> </li> <li class=md-nav__item> <a href=#getting-values class=md-nav__link> <span class=md-ellipsis> Getting values </span> </a> </li> <li class=md-nav__item> <a href=#metadata class=md-nav__link> <span class=md-ellipsis> Metadata </span> </a> </li> <li class=md-nav__item> <a href=#destruction class=md-nav__link> <span class=md-ellipsis> Destruction </span> </a> </li> </ul> </nav> </li> <li class=md-nav__item> <a href=#usage class=md-nav__link> <span class=md-ellipsis> Usage </span> </a> <nav class=md-nav aria-label=Usage> <ul class=md-nav__list> <li class=md-nav__item> <a href=#numerical-index class=md-nav__link> <span class=md-ellipsis> Numerical Index </span> </a> </li> <li class=md-nav__item> <a href=#associative-bash-4 class=md-nav__link> <span class=md-ellipsis> Associative (Bash 4) </span> </a> </li> <li class=md-nav__item> <a href=#integer-arrays class=md-nav__link> <span class=md-ellipsis> Integer arrays </span> </a> </li> <li class=md-nav__item> <a href=#indirection class=md-nav__link> <span class=md-ellipsis> Indirection </span> </a> </li> </ul> </nav> </li> <li class=md-nav__item> <a href=#bugs-and-portability-considerations class=md-nav__link> <span class=md-ellipsis> Bugs and Portability Considerations </span> </a> <nav class=md-nav aria-label="Bugs and Portability Considerations"> <ul class=md-nav__list> <li class=md-nav__item> <a href=#bugs class=md-nav__link> <span class=md-ellipsis> Bugs </span> </a> </li> </ul> </nav> </li> </ul> </nav> </li> <li class=md-nav__item> <a href=../basicgrammar/ class=md-nav__link> <span class=md-ellipsis> Basic grammar rules of Bash </span> </a> </li> <li class=md-nav__item> <a href=../pattern/ class=md-nav__link> <span class=md-ellipsis> Patterns and pattern matching </span> </a> </li> <li class=md-nav__item> <a href=../pe/ class=md-nav__link> <span class=md-ellipsis> Parameter expansion </span> </a> </li> <li class=md-nav__item> <a href=../quoting/ class=md-nav__link> <span class=md-ellipsis> Quotes and escaping </span> </a> </li> <li class=md-nav__item> <a href=../redirection/ class=md-nav__link> <span class=md-ellipsis> Redirection </span> </a> </li> <li class=md-nav__item> <a href=../shellvars/ class=md-nav__link> <span class=md-ellipsis> Special parameters and shell variables </span> </a> </li> <li class=md-nav__item> <a href=../words/ class=md-nav__link> <span class=md-ellipsis> Words... </span> </a> </li> <li class="md-nav__item md-nav__item--section md-nav__item--nested"> <input class="md-nav__toggle md-toggle " type=checkbox id=__nav_9_10> <label class=md-nav__link for=__nav_9_10 id=__nav_9_10_label tabindex> <span class=md-ellipsis> Ccmd </span> <span class="md-nav__icon md-icon"></span> </label> <nav class=md-nav data-md-level=2 aria-labelledby=__nav_9_10_label aria-expanded=false> <label class=md-nav__title for=__nav_9_10> <span class="md-nav__icon md-icon"></span> Ccmd </label> <ul class=md-nav__list data-md-scrollfix> <li class=md-nav__item> <a href=../ccmd/arithmetic_eval/ class=md-nav__link> <span class=md-ellipsis> Arithmetic evaluation (command) </span> </a> </li> <li class=md-nav__item> <a href=../ccmd/c_for/ class=md-nav__link> <span class=md-ellipsis> The C-style for-loop </span> </a> </li> <li class=md-nav__item> <a href=../ccmd/case/ class=md-nav__link> <span class=md-ellipsis> The case statement </span> </a> </li> <li class=md-nav__item> <a href=../ccmd/classic_for/ class=md-nav__link> <span class=md-ellipsis> The classic for-loop </span> </a> </li> <li class=md-nav__item> <a href=../ccmd/conditional_expression/ class=md-nav__link> <span class=md-ellipsis> The conditional expression </span> </a> </li> <li class=md-nav__item> <a href=../ccmd/grouping_plain/ class=md-nav__link> <span class=md-ellipsis> Grouping commands </span> </a> </li> <li class=md-nav__item> <a href=../ccmd/grouping_subshell/ class=md-nav__link> <span class=md-ellipsis> Grouping commands in a subshell </span> </a> </li> <li class=md-nav__item> <a href=../ccmd/if_clause/ class=md-nav__link> <span class=md-ellipsis> The if-clause </span> </a> </li> <li class=md-nav__item> <a href=../ccmd/intro/ class=md-nav__link> <span class=md-ellipsis> Bash compound commands </span> </a> </li> <li class=md-nav__item> <a href=../ccmd/until_loop/ class=md-nav__link> <span class=md-ellipsis> The until loop </span> </a> </li> <li class=md-nav__item> <a href=../ccmd/user_select/ class=md-nav__link> <span class=md-ellipsis> User selections </span> </a> </li> <li class=md-nav__item> <a href=../ccmd/while_loop/ class=md-nav__link> <span class=md-ellipsis> The while-loop </span> </a> </li> </ul> </nav> </li> <li class="md-nav__item md-nav__item--section md-nav__item--nested"> <input class="md-nav__toggle md-toggle " type=checkbox id=__nav_9_11> <label class=md-nav__link for=__nav_9_11 id=__nav_9_11_label tabindex> <span class=md-ellipsis> Expansion </span> <span class="md-nav__icon md-icon"></span> </label> <nav class=md-nav data-md-level=2 aria-labelledby=__nav_9_11_label aria-expanded=false> <label class=md-nav__title for=__nav_9_11> <span class="md-nav__icon md-icon"></span> Expansion </label> <ul class=md-nav__list data-md-scrollfix> <li class=md-nav__item> <a href=../expansion/arith/ class=md-nav__link> <span class=md-ellipsis> Arithmetic expansion </span> </a> </li> <li class=md-nav__item> <a href=../expansion/brace/ class=md-nav__link> <span class=md-ellipsis> Brace expansion </span> </a> </li> <li class=md-nav__item> <a href=../expansion/cmdsubst/ class=md-nav__link> <span class=md-ellipsis> Command substitution </span> </a> </li> <li class=md-nav__item> <a href=../expansion/globs/ class=md-nav__link> <span class=md-ellipsis> Pathname expansion (globbing) </span> </a> </li> <li class=md-nav__item> <a href=../expansion/intro/ class=md-nav__link> <span class=md-ellipsis> Expansions and substitutions </span> </a> </li> <li class=md-nav__item> <a href=../expansion/proc_subst/ class=md-nav__link> <span class=md-ellipsis> Process substitution </span> </a> </li> <li class=md-nav__item> <a href=../expansion/tilde/ class=md-nav__link> <span class=md-ellipsis> Tilde expansion </span> </a> </li> <li class=md-nav__item> <a href=../expansion/wordsplit/ class=md-nav__link> <span class=md-ellipsis> Word splitting </span> </a> </li> </ul> </nav> </li> <li class="md-nav__item md-nav__item--section md-nav__item--nested"> <input class="md-nav__toggle md-toggle " type=checkbox id=__nav_9_12> <label class=md-nav__link for=__nav_9_12 id=__nav_9_12_label tabindex> <span class=md-ellipsis> Grammar </span> <span class="md-nav__icon md-icon"></span> </label> <nav class=md-nav data-md-level=2 aria-labelledby=__nav_9_12_label aria-expanded=false> <label class=md-nav__title for=__nav_9_12> <span class="md-nav__icon md-icon"></span> Grammar </label> <ul class=md-nav__list data-md-scrollfix> <li class=md-nav__item> <a href=../grammar/parser_exec/ class=md-nav__link> <span class=md-ellipsis> Parser exec </span> </a> </li> </ul> </nav> </li> <li class="md-nav__item md-nav__item--section md-nav__item--nested"> <input class="md-nav__toggle md-toggle " type=checkbox id=__nav_9_13> <label class=md-nav__link for=__nav_9_13 id=__nav_9_13_label tabindex> <span class=md-ellipsis> Keywords </span> <span class="md-nav__icon md-icon"></span> </label> <nav class=md-nav data-md-level=2 aria-labelledby=__nav_9_13_label aria-expanded=false> <label class=md-nav__title for=__nav_9_13> <span class="md-nav__icon md-icon"></span> Keywords </label> <ul class=md-nav__list data-md-scrollfix> <li class=md-nav__item> <a href=../keywords/coproc/ class=md-nav__link> <span class=md-ellipsis> The coproc keyword </span> </a> </li> </ul> </nav> </li> </ul> </nav> </li> <li class=md-nav__item> <a href=../../tags/ class=md-nav__link> <span class=md-ellipsis> Tags </span> </a> </li> </ul> </nav> </div> </div> </div> <div class="md-sidebar md-sidebar--secondary" data-md-component=sidebar data-md-type=toc> <div class=md-sidebar__scrollwrap> <div class=md-sidebar__inner> <nav class="md-nav md-nav--secondary" aria-label="Table of contents"> <label class=md-nav__title for=__toc> <span class="md-nav__icon md-icon"></span> Table of contents </label> <ul class=md-nav__list data-md-component=toc data-md-scrollfix> <li class=md-nav__item> <a href=#purpose class=md-nav__link> <span class=md-ellipsis> Purpose </span> </a> </li> <li class=md-nav__item> <a href=#indexing class=md-nav__link> <span class=md-ellipsis> Indexing </span> </a> </li> <li class=md-nav__item> <a href=#syntax class=md-nav__link> <span class=md-ellipsis> Syntax </span> </a> <nav class=md-nav aria-label=Syntax> <ul class=md-nav__list> <li class=md-nav__item> <a href=#referencing class=md-nav__link> <span class=md-ellipsis> Referencing </span> </a> </li> <li class=md-nav__item> <a href=#declaration class=md-nav__link> <span class=md-ellipsis> Declaration </span> </a> </li> <li class=md-nav__item> <a href=#storing-values class=md-nav__link> <span class=md-ellipsis> Storing values </span> </a> </li> <li class=md-nav__item> <a href=#getting-values class=md-nav__link> <span class=md-ellipsis> Getting values </span> </a> </li> <li class=md-nav__item> <a href=#metadata class=md-nav__link> <span class=md-ellipsis> Metadata </span> </a> </li> <li class=md-nav__item> <a href=#destruction class=md-nav__link> <span class=md-ellipsis> Destruction </span> </a> </li> </ul> </nav> </li> <li class=md-nav__item> <a href=#usage class=md-nav__link> <span class=md-ellipsis> Usage </span> </a> <nav class=md-nav aria-label=Usage> <ul class=md-nav__list> <li class=md-nav__item> <a href=#numerical-index class=md-nav__link> <span class=md-ellipsis> Numerical Index </span> </a> </li> <li class=md-nav__item> <a href=#associative-bash-4 class=md-nav__link> <span class=md-ellipsis> Associative (Bash 4) </span> </a> </li> <li class=md-nav__item> <a href=#integer-arrays class=md-nav__link> <span class=md-ellipsis> Integer arrays </span> </a> </li> <li class=md-nav__item> <a href=#indirection class=md-nav__link> <span class=md-ellipsis> Indirection </span> </a> </li> </ul> </nav> </li> <li class=md-nav__item> <a href=#bugs-and-portability-considerations class=md-nav__link> <span class=md-ellipsis> Bugs and Portability Considerations </span> </a> <nav class=md-nav aria-label="Bugs and Portability Considerations"> <ul class=md-nav__list> <li class=md-nav__item> <a href=#bugs class=md-nav__link> <span class=md-ellipsis> Bugs </span> </a> </li> </ul> </nav> </li> </ul> </nav> </div> </div> </div> <div class=md-content data-md-component=content> <article class="md-content__inner md-typeset"> <a href=https://github.com/flokoe/bash-hackers-wiki/edit/main/docs/syntax/arrays.md title="Edit this page" class="md-content__button md-icon"> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 24 24"><path d="M10 20H6V4h7v5h5v3.1l2-2V8l-6-6H6c-1.1 0-2 .9-2 2v16c0 1.1.9 2 2 2h4zm10.2-7c.1 0 .3.1.4.2l1.3 1.3c.2.2.2.6 0 .8l-1 1-2.1-2.1 1-1c.1-.1.2-.2.4-.2m0 3.9L14.1 23H12v-2.1l6.1-6.1z"/></svg> </a> <a href=https://github.com/flokoe/bash-hackers-wiki/raw/main/docs/syntax/arrays.md title="View source of this page" class="md-content__button md-icon"> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 24 24"><path d="M17 18c.56 0 1 .44 1 1s-.44 1-1 1-1-.44-1-1 .44-1 1-1m0-3c-2.73 0-5.06 1.66-6 4 .94 2.34 3.27 4 6 4s5.06-1.66 6-4c-.94-2.34-3.27-4-6-4m0 6.5a2.5 2.5 0 0 1-2.5-2.5 2.5 2.5 0 0 1 2.5-2.5 2.5 2.5 0 0 1 2.5 2.5 2.5 2.5 0 0 1-2.5 2.5M9.27 20H6V4h7v5h5v4.07c.7.08 1.36.25 2 .49V8l-6-6H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h4.5a8.2 8.2 0 0 1-1.23-2"/></svg> </a> <h1 id=arrays>Arrays<a class=headerlink href=#arrays title="Permanent link">¶</a></h1> <h2 id=purpose>Purpose<a class=headerlink href=#purpose title="Permanent link">¶</a></h2> <p>An array is a parameter that holds mappings from keys to values. Arrays are used to store a collection of parameters into a parameter. Arrays (in any programming language) are a useful and common composite data structure, and one of the most important scripting features in Bash and other shells.</p> <p>Here is an <strong>abstract</strong> representation of an array named <code>NAMES</code>. The indexes go from 0 to 3.</p> <div class=highlight><pre><span></span><code>NAMES
|
|
0: Peter
|
|
1: Anna
|
|
2: Greg
|
|
3: Jan
|
|
</code></pre></div> <p>Instead of using 4 separate variables, multiple related variables are grouped grouped together into <em>elements</em> of the array, accessible by their <em>key</em>. If you want the second name, ask for index 1 of the array <code>NAMES</code>.</p> <h2 id=indexing>Indexing<a class=headerlink href=#indexing title="Permanent link">¶</a></h2> <p>Bash supports two different types of ksh-like one-dimensional arrays. <strong>Multidimensional arrays are not implemented</strong>.</p> <ul> <li><em>Indexed arrays</em> use positive integer numbers as keys. Indexed arrays are <strong>always sparse</strong>, meaning indexes are not necessarily contiguous. All syntax used for both assigning and dereferencing indexed arrays is an <a href=../arith_expr/ >arithmetic evaluation context</a> (see <a href=#Referencing>#Referencing</a>). As in C and many other languages, the numerical array indexes start at 0 (zero). Indexed arrays are the most common, useful, and portable type. Indexed arrays were first introduced to Bourne-like shells by ksh88. Similar, partially compatible syntax was inherited by many derivatives including Bash. Indexed arrays always carry the <code>-a</code> attribute.</li> <li><em>Associative arrays</em> (sometimes known as a "hash" or "dict") use arbitrary nonempty strings as keys. In other words, associative arrays allow you to look up a value from a table based upon its corresponding string label. <strong>Associative arrays are always unordered</strong>, they merely <em>associate</em> key-value pairs. If you retrieve multiple values from the array at once, you can't count on them coming out in the same order you put them in. Associative arrays always carry the <code>-A</code> attribute, and unlike indexed arrays, Bash requires that they always be declared explicitly (as indexed arrays are the default, see <a href=#Declaration>declaration</a>). Associative arrays were first introduced in ksh93, and similar mechanisms were later adopted by Zsh and Bash version 4. These three are currently the only POSIX-compatible shells with any associative array support.</li> </ul> <h2 id=syntax>Syntax<a class=headerlink href=#syntax title="Permanent link">¶</a></h2> <h3 id=referencing>Referencing<a class=headerlink href=#referencing title="Permanent link">¶</a></h3> <p>To accommodate referring to array variables and their individual elements, Bash extends the parameter naming scheme with a subscript suffix. Any valid ordinary scalar parameter name is also a valid array name: <code>[[:alpha:]_][[:alnum:]_]*</code>. The parameter name may be followed by an optional subscript enclosed in square brackets to refer to a member of the array.</p> <p>The overall syntax is <code>arrname[subscript]</code> - where for indexed arrays, <code>subscript</code> is any valid arithmetic expression, and for associative arrays, any nonempty string. Subscripts are first processed for parameter and arithmetic expansions, and command and process substitutions. When used within parameter expansions or as an argument to the <a href=../../commands/builtin/unset/ >unset</a> builtin, the special subscripts <code>*</code> and <code>@</code> are also accepted which act upon arrays analogously to the way the <code>@</code> and <code>*</code> special parameters act upon the positional parameters. In parsing the subscript, bash ignores any text that follows the closing bracket up to the end of the parameter name.</p> <p>With few exceptions, names of this form may be used anywhere ordinary parameter names are valid, such as within <a href=../arith_expr/ >arithmetic expressions</a>, <a href=../pe/ >parameter expansions</a>, and as arguments to builtins that accept parameter names. An <em>array</em> is a Bash parameter that has been given the <code>-a</code> (for indexed) or <code>-A</code> (for associative) <em>attributes</em>. However, any regular (non-special or positional) parameter may be validly referenced using a subscript, because in most contexts, referring to the zeroth element of an array is synonymous with referring to the array name without a subscript.</p> <div class=highlight><pre><span></span><code># "x" is an ordinary non-array parameter.
|
|
$ x=hi; printf '%s ' "$x" "${x[0]}"; echo "${_[0]}"
|
|
hi hi hi
|
|
</code></pre></div> <p>The only exceptions to this rule are in a few cases where the array variable's name refers to the array as a whole. This is the case for the <code>unset</code> builtin (see <a href=#Destruction>destruction</a>) and when declaring an array without assigning any values (see <a href=#Declaration>declaration</a>).</p> <h3 id=declaration>Declaration<a class=headerlink href=#declaration title="Permanent link">¶</a></h3> <p>The following explicitly give variables array attributes, making them arrays:</p> <table> <thead> <tr> <th>Syntax</th> <th>Description</th> </tr> </thead> <tbody> <tr> <td><code>ARRAY=()</code></td> <td>Declares an <strong>indexed</strong> array <code>ARRAY</code> and initializes it to be empty. This can also be used to empty an existing array.</td> </tr> <tr> <td><code>ARRAY[0]=</code></td> <td>Generally sets the first element of an <strong>indexed</strong> array. If no array <code>ARRAY</code> existed before, it is created.</td> </tr> <tr> <td><code>declare -a ARRAY</code></td> <td>Declares an <strong>indexed</strong> array <code>ARRAY</code>. An existing array is not initialized.</td> </tr> <tr> <td><code>declare -A ARRAY</code></td> <td>Declares an <strong>associative</strong> array <code>ARRAY</code>. This is the one and only way to create associative arrays.</td> </tr> </tbody> </table> <p>As an example, and for use below, let's declare our <code>NAMES</code> array as described <a href=#purpose>above</a>:</p> <div class=highlight><pre><span></span><code> declare -a NAMES=('Peter' 'Anna' 'Greg' 'Jan')
|
|
</code></pre></div> <h3 id=storing-values>Storing values<a class=headerlink href=#storing-values title="Permanent link">¶</a></h3> <p>Storing values in arrays is quite as simple as storing values in normal variables.</p> <table> <thead> <tr> <th>Syntax</th> <th>Description</th> </tr> </thead> <tbody> <tr> <td><code>ARRAY[N]=VALUE</code></td> <td>Sets the element <code>N</code> of the <strong>indexed</strong> array <code>ARRAY</code> to <code>VALUE</code>. <strong><code>N</code> can be any valid <a href=../arith_expr/ >arithmetic expression</a></strong>.</td> </tr> <tr> <td><code>ARRAY[STRING]=VALUE</code></td> <td>Sets the element indexed by <code>STRING</code> of the <strong>associative array</strong> <code>ARRAY</code>.</td> </tr> <tr> <td><code>ARRAY=VALUE</code></td> <td>As above. If no index is given, as a default the zeroth element is set to <code>VALUE</code>. Careful, this is even true of associative arrays - there is no error if no key is specified, and the value is assigned to string index "0".</td> </tr> <tr> <td><code>ARRAY=(E1\ E2\ ...)</code></td> <td>Compound array assignment - sets the whole array <code>ARRAY</code> to the given list of elements indexed sequentially starting at zero. The array is unset before assignment unless the += operator is used. When the list is empty (<code>ARRAY=()</code>), the array will be set to an empty array. This method obviously does not use explicit indexes. An <strong>associative array</strong> can <strong>not</strong> be set like that! Clearing an associative array using <code>ARRAY=()</code> works.</td> </tr> <tr> <td><code>ARRAY=([X]=E1\ [Y]=E2\ ...)</code></td> <td>Compound assignment for indexed arrays with index-value pairs declared individually (here for example <code>X</code> and <code>Y</code>). X and Y are arithmetic expressions. This syntax can be combined with the above - elements declared without an explicitly specified index are assigned sequentially starting at either the last element with an explicit index, or zero.</td> </tr> <tr> <td><code>ARRAY=([S1]=E1\ [S2]=E2\ ...)</code></td> <td>Individual mass-setting for <strong>associative arrays</strong>. The named indexes (here: <code>S1</code> and <code>S2</code>) are strings.</td> </tr> <tr> <td><code>ARRAY+=(E1\ E2\ ...)</code></td> <td>Append to ARRAY.</td> </tr> <tr> <td><code>ARRAY=("${ANOTHER_ARRAY[@]}")</code></td> <td>Copy ANOTHER_ARRAY to ARRAY, copying each element.</td> </tr> </tbody> </table> <p>As of now, arrays can't be exported.</p> <h3 id=getting-values>Getting values<a class=headerlink href=#getting-values title="Permanent link">¶</a></h3> <div class="admonition info"> <p>For completeness and details on several parameter expansion variants, see the <a href=../pe/ >article about parameter expansion</a> and check the notes about arrays.</p> </div> <table> <thead> <tr> <th>Syntax</th> <th>Description</th> </tr> </thead> <tbody> <tr> <td><code>${ARRAY[N]}</code></td> <td>Expands to the value of the index <code>N</code> in the <strong>indexed</strong> array <code>ARRAY</code>. If <code>N</code> is a negative number, it's treated as the offset from the maximum assigned index (can't be used for assignment) - 1</td> </tr> <tr> <td><code>${ARRAY[S]}</code></td> <td>Expands to the value of the index <code>S</code> in the <strong>associative</strong> array <code>ARRAY</code>.</td> </tr> <tr> <td><code>"${ARRAY[@]}" ${ARRAY[@]} "${ARRAY[*]}" ${ARRAY[*]}</code></td> <td>Similar to <a href=../../scripting/posparams/#mass_usage>mass-expanding positional parameters</a>, this expands to all elements. If unquoted, both subscripts <code>*</code> and <code>@</code> expand to the same result, if quoted, <code>@</code> expands to all elements individually quoted, <code>*</code> expands to all elements quoted as a whole.</td> </tr> <tr> <td><code>"${ARRAY[@]:N:M}" ${ARRAY[@]:N:M} "${ARRAY[*]:N:M}" ${ARRAY[*]:N:M}</code></td> <td>Similar to what this syntax does for the characters of a single string when doing <a href=../pe/#substring_expansion>substring expansion</a>, this expands to <code>M</code> elements starting with element <code>N</code>. This way you can mass-expand individual indexes. The rules for quoting and the subscripts <code>*</code> and <code>@</code> are the same as above for the other mass-expansions.</td> </tr> </tbody> </table> <p>For clarification: When you use the subscripts <code>@</code> or <code>*</code> for mass-expanding, then the behaviour is exactly what it is for <code>$@</code> and <code>$*</code> when <a href=../../scripting/posparams/#mass_usage>mass-expanding the positional parameters</a>. You should read this article to understand what's going on.</p> <h3 id=metadata>Metadata<a class=headerlink href=#metadata title="Permanent link">¶</a></h3> <table> <thead> <tr> <th>Syntax</th> <th>Description</th> </tr> </thead> <tbody> <tr> <td><code>${#ARRAY[N]}</code></td> <td>Expands to the <strong>length</strong> of an individual array member at index <code>N</code> (<strong>stringlength</strong>)</td> </tr> <tr> <td><code>${#ARRAY[STRING]}</code></td> <td>Expands to the <strong>length</strong> of an individual associative array member at index <code>STRING</code> (<strong>stringlength</strong>)</td> </tr> <tr> <td><code>${#ARRAY[@]}</code> \ <code>${#ARRAY[*]}</code></td> <td>Expands to the <strong>number of elements</strong> in <code>ARRAY</code></td> </tr> <tr> <td><code>${!ARRAY[@]}</code> \ <code>${!ARRAY[*]}</code></td> <td>Expands to the <strong>indexes</strong> in <code>ARRAY</code> since BASH 3.0</td> </tr> </tbody> </table> <h3 id=destruction>Destruction<a class=headerlink href=#destruction title="Permanent link">¶</a></h3> <p>The <a href=../../commands/builtin/unset/ >unset</a> builtin command is used to destroy (unset) arrays or individual elements of arrays.</p> <table> <thead> <tr> <th>Syntax</th> <th>Description</th> </tr> </thead> <tbody> <tr> <td><code>unset -v ARRAY</code> \ <code>unset -v ARRAY[@]</code> \ <code>unset -v ARRAY[*]</code></td> <td>Destroys a complete array</td> </tr> <tr> <td><code>unset -v ARRAY[N]</code></td> <td>Destroys the array element at index <code>N</code></td> </tr> <tr> <td><code>unset -v ARRAY[STRING]</code></td> <td>Destroys the array element of the associative array at index <code>STRING</code></td> </tr> </tbody> </table> <p>It is best to <a href=../../commands/builtin/unset/#portability_considerations>explicitly specify -v</a> when unsetting variables with unset.</p> <div class="admonition warning"> <p class=admonition-title>warning</p> <p>Specifying unquoted array elements as arguments to any command, such as with the syntax above <strong>may cause <a href=../expansion/globs/ >pathname expansion</a> to occur</strong> due to the presence of glob characters.</p> <p>Example: You are in a directory with a file named <code>x1</code>, and you want to destroy an array element <code>x[1]</code>, with</p> <div class=highlight><pre><span></span><code>unset x[1]
|
|
</code></pre></div> <p>then pathname expansion will expand to the filename <code>x1</code> and break your processing!</p> <p>Even worse, if <code>nullglob</code> is set, your array/index will disappear.</p> <p>To avoid this, <strong>always quote</strong> the array name and index:</p> <div class=highlight><pre><span></span><code>unset -v 'x[1]'
|
|
</code></pre></div> <p>This applies generally to all commands which take variable names as arguments. Single quotes preferred.</p> </div> <h2 id=usage>Usage<a class=headerlink href=#usage title="Permanent link">¶</a></h2> <h3 id=numerical-index>Numerical Index<a class=headerlink href=#numerical-index title="Permanent link">¶</a></h3> <p>Numerical indexed arrays are easy to understand and easy to use. The <a href=#purpose>Purpose</a> and <a href=#indexing>Indexing</a> chapters above more or less explain all the needed background theory.</p> <p>Now, some examples and comments for you.</p> <p>Let's say we have an array <code>sentence</code> which is initialized as follows:</p> <div class=highlight><pre><span></span><code>sentence=(Be liberal in what you accept, and conservative in what you send)
|
|
</code></pre></div> <p>Since no special code is there to prevent word splitting (no quotes), every word there will be assigned to an individual array element. When you count the words you see, you should get 12. Now let's see if Bash has the same opinion:</p> <div class=highlight><pre><span></span><code>$ echo ${#sentence[@]}
|
|
12
|
|
</code></pre></div> <p>Yes, 12. Fine. You can take this number to walk through the array. Just <strong>subtract 1 from the number of elements, and start your walk at 0 (zero)</strong>:</p> <div class=highlight><pre><span></span><code>((n_elements=${#sentence[@]}, max_index=n_elements - 1))
|
|
|
|
for ((i = 0; i <= max_index; i++)); do
|
|
echo "Element $i: '${sentence[i]}'"
|
|
done
|
|
</code></pre></div> <p>You always have to remember that, it seems newbies have problems sometimes. Please understand that <strong>numerical array indexing begins at 0 (zero)</strong>!</p> <p>The method above, walking through an array by just knowing its number of elements, only works for arrays where all elements are set, of course. If one element in the middle is removed, then the calculation is nonsense, because the number of elements doesn't correspond to the highest used index anymore (we call them "<em>sparse arrays</em>").</p> <p>Now, suppose that you want to replace your array <code>sentence</code> with the values in the <a href=#purpose>previously-declared array</a> <code>NAMES</code> . You might think you could just do</p> <div class=highlight><pre><span></span><code>$ unset sentence ; declare -a sentence=NAMES
|
|
$ echo ${#sentence[@]}
|
|
1
|
|
# omit calculating max_index as above, and iterate as one-liner
|
|
$ for ((i = 0; i < ${#sentence[@]}; i++)); do echo "Element $i: '${sentence[i]}'" ; done
|
|
Element 0: 'NAMES'
|
|
</code></pre></div> <p>Obviously that's wrong. What about</p> <div class=highlight><pre><span></span><code>$ unset sentence ; declare -a sentence=${NAMES}
|
|
</code></pre></div> <p>? Again, wrong:</p> <div class=highlight><pre><span></span><code>$ echo ${#sentence[*]}
|
|
1
|
|
$ for ((i = 0; i < ${#sentence[@]}; i++)); do echo "Element $i: '${sentence[i]}'" ; done
|
|
Element 0: 'Peter'
|
|
</code></pre></div> <p>So what's the <strong>right</strong> way? The (slightly ugly) answer is, reuse the enumeration syntax:</p> <div class=highlight><pre><span></span><code>$ unset sentence ; declare -a sentence=("${NAMES[@]}")
|
|
$ echo ${#sentence[@]}
|
|
4
|
|
$ for ((i = 0; i < ${#sentence[@]}; i++)); do echo "Element $i: '${sentence[i]}'" ; done
|
|
Element 0: 'Peter'
|
|
Element 1: 'Anna'
|
|
Element 2: 'Greg'
|
|
Element 3: 'Jan'
|
|
</code></pre></div> <h3 id=associative-bash-4>Associative (Bash 4)<a class=headerlink href=#associative-bash-4 title="Permanent link">¶</a></h3> <p>Associative arrays (or <em>hash tables</em>) are not much more complicated than numerical indexed arrays. The numerical index value (in Bash a number starting at zero) just is replaced with an arbitrary string:</p> <div class=highlight><pre><span></span><code># declare -A, introduced with Bash 4 to declare an associative array
|
|
declare -A sentence
|
|
|
|
sentence[Begin]='Be liberal in what'
|
|
sentence[Middle]='you accept, and conservative'
|
|
sentence[End]='in what you send'
|
|
sentence['Very end']=...
|
|
</code></pre></div> <p><u><strong>Beware:</strong></u> don't rely on the fact that the elements are ordered in memory like they were declared, it could look like this:</p> <div class=highlight><pre><span></span><code># output from 'set' command
|
|
sentence=([End]="in what you send" [Middle]="you accept, and conservative " [Begin]="Be liberal in what " ["Very end"]="...")
|
|
</code></pre></div> <p>This effectively means, you can get the data back with <code>"${sentence[@]}"</code>, of course (just like with numerical indexing), but you can't rely on a specific order. If you want to store ordered data, or re-order data, go with numerical indexes. For associative arrays, you usually query known index values:</p> <div class=highlight><pre><span></span><code>for element in Begin Middle End "Very end"; do
|
|
printf "%s" "${sentence[$element]}"
|
|
done
|
|
printf "\n"
|
|
</code></pre></div> <p><strong>A nice code example:</strong> Checking for duplicate files using an associative array indexed with the SHA sum of the files:</p> <div class=highlight><pre><span></span><code># Thanks to Tramp in #bash for the idea and the code
|
|
|
|
unset flist; declare -A flist;
|
|
while read -r sum fname; do
|
|
if [[ ${flist[$sum]} ]]; then
|
|
printf 'rm -- "%s" # Same as >%s<\n' "$fname" "${flist[$sum]}"
|
|
else
|
|
flist[$sum]="$fname"
|
|
fi
|
|
done < <(find . -type f -exec sha256sum {} +) >rmdups
|
|
</code></pre></div> <h3 id=integer-arrays>Integer arrays<a class=headerlink href=#integer-arrays title="Permanent link">¶</a></h3> <p>Any type attributes applied to an array apply to all elements of the array. If the integer attribute is set for either indexed or associative arrays, then values are considered as arithmetic for both compound and ordinary assignment, and the += operator is modified in the same way as for ordinary integer variables.</p> <div class=highlight><pre><span></span><code> ~ $ ( declare -ia 'a=(2+4 [2]=2+2 [a[2]]="a[2]")' 'a+=(42 [a[4]]+=3)'; declare -p a )
|
|
declare -ai a='([0]="6" [2]="4" [4]="7" [5]="42")'
|
|
</code></pre></div> <p><code>a[0]</code> is assigned to the result of <code>2+4</code>. <code>a[2]</code> gets the result of <code>2+2</code>. The last index in the first assignment is the result of <code>a[2]</code>, which has already been assigned as <code>4</code>, and its value is also given <code>a[2]</code>.</p> <p>This shows that even though any existing arrays named <code>a</code> in the current scope have already been unset by using <code>=</code> instead of <code>+=</code> to the compound assignment, arithmetic variables within keys can self-reference any elements already assigned within the same compound-assignment. With integer arrays this also applies to expressions to the right of the <code>=</code>. (See <a href=#evaluation_order>evaluation order</a>, the right side of an arithmetic assignment is typically evaluated first in Bash.)</p> <p>The second compound assignment argument to declare uses <code>+=</code>, so it appends after the last element of the existing array rather than deleting it and creating a new array, so <code>a[5]</code> gets <code>42</code>.</p> <p>Lastly, the element whose index is the value of <code>a[4]</code> (<code>4</code>), gets <code>3</code> added to its existing value, making <code>a[4]</code> == <code>7</code>. Note that having the integer attribute set this time causes += to add, rather than append a string, as it would for a non-integer array.</p> <p>The single quotes force the assignments to be evaluated in the environment of <code>declare</code>. This is important because attributes are only applied to the assignment after assignment arguments are processed. Without them the <code>+=</code> compound assignment would have been invalid, and strings would have been inserted into the integer array without evaluating the arithmetic. A special-case of this is shown in the next section.</p> <div class="admonition info"> <p class=admonition-title>info</p> <p>Bash declaration commands are really keywords in disguise. They magically parse arguments to determine whether they are in the form of a valid assignment. If so, they are evaluated as assignments. If not, they are undergo normal argument expansion before being passed to the builtin which evaluates the resulting string as an assignment (somewhat like <code>eval</code>, but there are differences.) <code>'Todo:</code>\' Discuss this in detail.</p> </div> <h3 id=indirection>Indirection<a class=headerlink href=#indirection title="Permanent link">¶</a></h3> <p>Arrays can be expanded indirectly using the indirect parameter expansion syntax. Parameters whose values are of the form: <code>name[index]</code>, <code>name[@]</code>, or <code>name[*]</code> when expanded indirectly produce the expected results. This is mainly useful for passing arrays (especially multiple arrays) by name to a function.</p> <p>This example is an "isSubset"-like predicate which returns true if all key-value pairs of the array given as the first argument to isSubset correspond to a key-value of the array given as the second argument. It demonstrates both indirect array expansion and indirect key-passing without eval using the aforementioned special compound assignment expansion.</p> <div class=highlight><pre><span></span><code>isSubset() {
|
|
local -a 'xkeys=("${!'"$1"'[@]}")' 'ykeys=("${!'"$2"'[@]}")'
|
|
set -- "${@/%/[key]}"
|
|
|
|
(( ${#xkeys[@]} <= ${#ykeys[@]} )) || return 1
|
|
|
|
local key
|
|
for key in "${xkeys[@]}"; do
|
|
[[ ${!2+_} && ${!1} == ${!2} ]] || return 1
|
|
done
|
|
}
|
|
|
|
main() {
|
|
# "a" is a subset of "b"
|
|
local -a 'a=({0..5})' 'b=({0..10})'
|
|
isSubset a b
|
|
echo $? # true
|
|
|
|
# "a" contains a key not in "b"
|
|
local -a 'a=([5]=5 {6..11})' 'b=({0..10})'
|
|
isSubset a b
|
|
echo $? # false
|
|
|
|
# "a" contains an element whose value != the corresponding member of "b"
|
|
local -a 'a=([5]=5 6 8 9 10)' 'b=({0..10})'
|
|
isSubset a b
|
|
echo $? # false
|
|
}
|
|
|
|
main
|
|
</code></pre></div> <p>This script is one way of implementing a crude multidimensional associative array by storing array definitions in an array and referencing them through indirection. The script takes two keys and dynamically calls a function whose name is resolved from the array.</p> <div class=highlight><pre><span></span><code>callFuncs() {
|
|
# Set up indirect references as positional parameters to minimize local name collisions.
|
|
set -- "${@:1:3}" ${2+'a["$1"]' "$1"'["$2"]'}
|
|
|
|
# The only way to test for set but null parameters is unfortunately to test each individually.
|
|
local x
|
|
for x; do
|
|
[[ $x ]] || return 0
|
|
done
|
|
|
|
local -A a=(
|
|
[foo]='([r]=f [s]=g [t]=h)'
|
|
[bar]='([u]=i [v]=j [w]=k)'
|
|
[baz]='([x]=l [y]=m [z]=n)'
|
|
) ${4+${a["$1"]+"${1}=${!3}"}} # For example, if "$1" is "bar" then define a new array: bar=([u]=i [v]=j [w]=k)
|
|
|
|
${4+${a["$1"]+"${!4-:}"}} # Now just lookup the new array. for inputs: "bar" "v", the function named "j" will be called, which prints "j" to stdout.
|
|
}
|
|
|
|
main() {
|
|
# Define functions named {f..n} which just print their own names.
|
|
local fun='() { echo "$FUNCNAME"; }' x
|
|
|
|
for x in {f..n}; do
|
|
eval "${x}${fun}"
|
|
done
|
|
|
|
callFuncs "$@"
|
|
}
|
|
|
|
main "$@"
|
|
</code></pre></div> <h2 id=bugs-and-portability-considerations>Bugs and Portability Considerations<a class=headerlink href=#bugs-and-portability-considerations title="Permanent link">¶</a></h2> <ul> <li>Arrays are not specified by POSIX. One-dimensional indexed arrays are supported using similar syntax and semantics by most Korn-like shells.</li> <li>Associative arrays are supported via <code>typeset -A</code> in Bash 4, Zsh, and Ksh93.</li> <li>In Ksh93, arrays whose types are not given explicitly are not necessarily indexed. Arrays defined using compound assignments which specify subscripts are associative by default. In Bash, associative arrays can <em>only</em> be created by explicitly declaring them as associative, otherwise they are always indexed. In addition, ksh93 has several other compound structures whose types can be determined by the compound assignment syntax used to create them.</li> <li>In Ksh93, using the <code>=</code> compound assignment operator unsets the array, including any attributes that have been set on the array prior to assignment. In order to preserve attributes, you must use the <code>+=</code> operator. However, declaring an associative array, then attempting an <code>a=(...)</code> style compound assignment without specifying indexes is an error. I can't explain this inconsistency.<code>$ ksh -c 'function f { typeset -a a; a=([0]=foo [1]=bar); typeset -p a; }; f' # Attribute is lost, and since subscripts are given, we default to associative. typeset -A a=([0]=foo [1]=bar) $ ksh -c 'function f { typeset -a a; a+=([0]=foo [1]=bar); typeset -p a; }; f' # Now using += gives us the expected results. typeset -a a=(foo bar) $ ksh -c 'function f { typeset -A a; a=(foo bar); typeset -p a; }; f' # On top of that, the reverse does NOT unset the attribute. No idea why. ksh: f: line 1: cannot append index array to associative array a</code></li> <li>Only Bash and mksh support compound assignment with mixed explicit subscripts and automatically incrementing subscripts. In ksh93, in order to specify individual subscripts within a compound assignment, all subscripts must be given (or none). Zsh doesn't support specifying individual subscripts at all.</li> <li>Appending to a compound assignment is a fairly portable way to append elements after the last index of an array. In Bash, this also sets append mode for all individual assignments within the compound assignment, such that if a lower subscript is specified, subsequent elements will be appended to previous values. In ksh93, it causes subscripts to be ignored, forcing appending everything after the last element. (Appending has different meaning due to support for multi-dimensional arrays and nested compound datastructures.) <code>$ ksh -c 'function f { typeset -a a; a+=(foo bar baz); a+=([3]=blah [0]=bork [1]=blarg [2]=zooj); typeset -p a; }; f' # ksh93 forces appending to the array, disregarding subscripts typeset -a a=(foo bar baz '[3]=blah' '[0]=bork' '[1]=blarg' '[2]=zooj') $ bash -c 'function f { typeset -a a; a+=(foo bar baz); a+=(blah [0]=bork blarg zooj); typeset -p a; }; f' # Bash applies += to every individual subscript. declare -a a='([0]="foobork" [1]="barblarg" [2]="bazzooj" [3]="blah")' $ mksh -c 'function f { typeset -a a; a+=(foo bar baz); a+=(blah [0]=bork blarg zooj); typeset -p a; }; f' # Mksh does like Bash, but clobbers previous values rather than appending. set -A a typeset a[0]=bork typeset a[1]=blarg typeset a[2]=zooj typeset a[3]=blah</code></li> <li>In Bash and Zsh, the alternate value assignment parameter expansion (<code>${arr[idx]:=foo}</code>) evaluates the subscript twice, first to determine whether to expand the alternate, and second to determine the index to assign the alternate to. See <a href=#evaluation_order>evaluation order</a>. <code>$ : ${_[$(echo $RANDOM >&2)1]:=$(echo hi >&2)} 13574 hi 14485</code></li> <li>In Zsh, arrays are indexed starting at 1 in its default mode. Emulation modes are required in order to get any kind of portability.</li> <li>Zsh and mksh do not support compound assignment arguments to <code>typeset</code>.</li> <li>Ksh88 didn't support modern compound array assignment syntax. The original (and most portable) way to assign multiple elements is to use the <code>set -A name arg1 arg2 ...</code> syntax. This is supported by almost all shells that support ksh-like arrays except for Bash. Additionally, these shells usually support an optional <code>-s</code> argument to <code>set</code> which performs lexicographic sorting on either array elements or the positional parameters. Bash has no built-in sorting ability other than the usual comparison operators. <code>$ ksh -c 'set -A arr -- foo bar bork baz; typeset -p arr' # Classic array assignment syntax typeset -a arr=(foo bar bork baz) $ ksh -c 'set -sA arr -- foo bar bork baz; typeset -p arr' # Native sorting! typeset -a arr=(bar baz bork foo) $ mksh -c 'set -sA arr -- foo "[3]=bar" "[2]=baz" "[7]=bork"; typeset -p arr' # Probably a bug. I think the maintainer is aware of it. set -A arr typeset arr[2]=baz typeset arr[3]=bar typeset arr[7]=bork typeset arr[8]=foo</code></li> <li>Evaluation order for assignments involving arrays varies significantly depending on context. Notably, the order of evaluating the subscript or the value first can change in almost every shell for both expansions and arithmetic variables. See <a href=#evaluation_order>evaluation order</a> for details.</li> <li>Bash 4.1.* and below cannot use negative subscripts to address array indexes relative to the highest-numbered index. You must use the subscript expansion, i.e. <code>"${arr[@]:(-n):1}"</code>, to expand the nth-last element (or the next-highest indexed after <code>n</code> if <code>arr[n]</code> is unset). In Bash 4.2, you may expand (but not assign to) a negative index. In Bash 4.3, ksh93, and zsh, you may both assign and expand negative offsets.</li> <li>ksh93 also has an additional slice notation: <code>"${arr[n..m]}"</code> where <code>n</code> and <code>m</code> are arithmetic expressions. These are needed for use with multi-dimensional arrays.</li> <li>Assigning or referencing negative indexes in mksh causes wrap-around. The max index appears to be <code>UINT_MAX</code>, which would be addressed by <code>arr[-1]</code>.</li> <li>So far, Bash's <code>-v var</code> test doesn't support individual array subscripts. You may supply an array name to test whether an array is defined, but can't check an element. ksh93's <code>-v</code> supports both. Other shells lack a <code>-v</code> test.</li> </ul> <h3 id=bugs>Bugs<a class=headerlink href=#bugs title="Permanent link">¶</a></h3> <ul> <li><strong>Fixed in 4.3</strong> Bash 4.2.* and earlier considers each chunk of a compound assignment, including the subscript for globbing. The subscript part is considered quoted, but any unquoted glob characters on the right-hand side of the <code>[...]=</code> will be clumped with the subscript and counted as a glob. Therefore, you must quote anything on the right of the <code>=</code> sign. This is fixed in 4.3, so that each subscript assignment statement is expanded following the same rules as an ordinary assignment. This also works correctly in ksh93. <code>$ touch '[1]=a'; bash -c 'a=([1]=*); echo "${a[@]}"' [1]=a</code> mksh has a similar but even worse problem in that the entire subscript is considered a glob. <code>$ touch 1=a; mksh -c 'a=([123]=*); print -r -- "${a[@]}"' 1=a</code></li> <li> <p><strong>Fixed in 4.3</strong> In addition to the above globbing issue, assignments preceding "declare" have an additional effect on brace and pathname expansion. `$ set -x; foo=bar declare arr=( {1..10} )</p> <ul> <li>foo=bar</li> <li>declare 'arr=(1)' 'arr=(2)' 'arr=(3)' 'arr=(4)' 'arr=(5)' 'arr=(6)' 'arr=(7)' 'arr=(8)' 'arr=(9)' 'arr=(10)'</li> </ul> <p>$ touch xy=foo + touch xy=foo $ declare x[y]=<em> + declare 'x[y]=</em>' $ foo=bar declare x[y]=* + foo=bar + declare xy=foo <code>Each word (the entire assignment) is subject to globbing and brace expansion. This appears to trigger the same strange expansion mode as</code>let<code>,</code>eval<code>, other declaration commands, and maybe more. - **Fixed in 4.3** Indirection combined with another modifier expands arrays to a single word.</code>$ a=({a..c}) b=a[@]; printf '<%s> ' "${!b}"; echo; printf '<%s> ' "${!b/%/foo}"; echo <a> <b> <c> <a b cfoo> <code>- **Fixed in 4.3** Process substitutions are evaluated within array indexes. Zsh and ksh don't do this in any arithmetic context.</code># print "moo" dev=fd=1 _[1<(echo moo >&2)]=</p> <h1 id=fork-bomb>Fork bomb<a class=headerlink href=#fork-bomb title="Permanent link">¶</a></h1> <p>${dev[${dev='dev[1>(${dev[dev]})]'}]} `</p> </li> </ul> <h3 id=evaluation-order>Evaluation order<a class=headerlink href=#evaluation-order title="Permanent link">¶</a></h3> <p>Here are some of the nasty details of array assignment evaluation order. You can use this <a href=https://gist.github.com/ormaaj/4942297>testcase code</a> to generate these results.</p> <div class=highlight><pre><span></span><code>Each testcase prints evaluation order for indexed array assignment
|
|
contexts. Each context is tested for expansions (represented by digits) and
|
|
arithmetic (letters), ordered from left to right within the expression. The
|
|
output corresponds to the way evaluation is re-ordered for each shell:
|
|
|
|
a[ $1 a ]=${b[ $2 b ]:=${c[ $3 c ]}} No attributes
|
|
a[ $1 a ]=${b[ $2 b ]:=c[ $3 c ]} typeset -ia a
|
|
a[ $1 a ]=${b[ $2 b ]:=c[ $3 c ]} typeset -ia b
|
|
a[ $1 a ]=${b[ $2 b ]:=c[ $3 c ]} typeset -ia a b
|
|
(( a[ $1 a ] = b[ $2 b ] ${c[ $3 c ]} )) No attributes
|
|
(( a[ $1 a ] = ${b[ $2 b ]:=c[ $3 c ]} )) typeset -ia b
|
|
a+=( [ $1 a ]=${b[ $2 b ]:=${c[ $3 c ]}} [ $4 d ]=$(( $5 e )) ) typeset -a a
|
|
a+=( [ $1 a ]=${b[ $2 b ]:=c[ $3 c ]} [ $4 d ]=${5}e ) typeset -ia a
|
|
|
|
bash: 4.2.42(1)-release
|
|
2 b 3 c 2 b 1 a
|
|
2 b 3 2 b 1 a c
|
|
2 b 3 2 b c 1 a
|
|
2 b 3 2 b c 1 a c
|
|
1 2 3 c b a
|
|
1 2 b 3 2 b c c a
|
|
1 2 b 3 c 2 b 4 5 e a d
|
|
1 2 b 3 2 b 4 5 a c d e
|
|
|
|
ksh93: Version AJM 93v- 2013-02-22
|
|
1 2 b b a
|
|
1 2 b b a
|
|
1 2 b b a
|
|
1 2 b b a
|
|
1 2 3 c b a
|
|
1 2 b b a
|
|
1 2 b b a 4 5 e d
|
|
1 2 b b a 4 5 d e
|
|
|
|
mksh: @(#)MIRBSD KSH R44 2013/02/24
|
|
2 b 3 c 1 a
|
|
2 b 3 1 a c
|
|
2 b 3 c 1 a
|
|
2 b 3 c 1 a
|
|
1 2 3 c a b
|
|
1 2 b 3 c a
|
|
1 2 b 3 c 4 5 e a d
|
|
1 2 b 3 4 5 a c d e
|
|
|
|
zsh: 5.0.2
|
|
2 b 3 c 2 b 1 a
|
|
2 b 3 2 b 1 a c
|
|
2 b 1 a
|
|
2 b 1 a
|
|
1 2 3 c b a
|
|
1 2 b a
|
|
1 2 b 3 c 2 b 4 5 e
|
|
1 2 b 3 2 b 4 5
|
|
</code></pre></div> <h2 id=see-also>See also<a class=headerlink href=#see-also title="Permanent link">¶</a></h2> <ul> <li><a href=../pe/ >Parameter expansion</a> (contains sections for arrays)</li> <li><a href=../ccmd/classic_for/ >classic_for</a> (contains some examples to iterate over arrays)</li> <li><a href=../../commands/builtin/declare/ >declare</a></li> <li><a href=http://mywiki.wooledge.org/BashFAQ/005>BashFAQ 005 - How can I use array variables?</a> - A very detailed discussion on arrays with many examples.</li> <li><a href=http://mywiki.wooledge.org/BashSheet#Arrays>BashSheet - Arrays</a> - Bashsheet quick-reference on Greycat's wiki.</li> </ul> <aside class=md-source-file> <span class=md-source-file__fact> <span class=md-icon title="Last update"> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 24 24"><path d="M21 13.1c-.1 0-.3.1-.4.2l-1 1 2.1 2.1 1-1c.2-.2.2-.6 0-.8l-1.3-1.3c-.1-.1-.2-.2-.4-.2m-1.9 1.8-6.1 6V23h2.1l6.1-6.1zM12.5 7v5.2l4 2.4-1 1L11 13V7zM11 21.9c-5.1-.5-9-4.8-9-9.9C2 6.5 6.5 2 12 2c5.3 0 9.6 4.1 10 9.3-.3-.1-.6-.2-1-.2s-.7.1-1 .2C19.6 7.2 16.2 4 12 4c-4.4 0-8 3.6-8 8 0 4.1 3.1 7.5 7.1 7.9l-.1.2z"/></svg> </span> <span class="git-revision-date-localized-plugin git-revision-date-localized-plugin-date">November 13, 2024</span> </span> <span class=md-source-file__fact> <span class=md-icon title=Created> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 24 24"><path d="M14.47 15.08 11 13V7h1.5v5.25l3.08 1.83c-.41.28-.79.62-1.11 1m-1.39 4.84c-.36.05-.71.08-1.08.08-4.42 0-8-3.58-8-8s3.58-8 8-8 8 3.58 8 8c0 .37-.03.72-.08 1.08.69.1 1.33.32 1.92.64.1-.56.16-1.13.16-1.72 0-5.5-4.5-10-10-10S2 6.5 2 12s4.47 10 10 10c.59 0 1.16-.06 1.72-.16-.32-.59-.54-1.23-.64-1.92M18 15v3h-3v2h3v3h2v-3h3v-2h-3v-3z"/></svg> </span> <span class="git-revision-date-localized-plugin git-revision-date-localized-plugin-date">November 13, 2024</span> </span> </aside> <h2 id=__comments>Comments</h2> <script src=https://giscus.app/client.js data-repo=flokoe/bash-hackers-wiki data-repo-id=R_kgDOJ3Nr6Q data-category="Giscus Page Comments" data-category-id=DIC_kwDOJ3Nr6c4CXq9t data-mapping=pathname data-strict=1 data-reactions-enabled=1 data-emit-metadata=0 data-input-position=top data-theme=preferred_color_scheme data-lang=en data-loading=lazy crossorigin=anonymous async>
|
|
</script> <script>
|
|
var giscus = document.querySelector("script[src*=giscus]")
|
|
|
|
/* Set palette on initial load */
|
|
var palette = __md_get("__palette")
|
|
if (palette && typeof palette.color === "object") {
|
|
var theme = palette.color.scheme === "slate" ? "dark" : "light"
|
|
giscus.setAttribute("data-theme", theme)
|
|
}
|
|
|
|
/* Register event handlers after documented loaded */
|
|
document.addEventListener("DOMContentLoaded", function() {
|
|
var ref = document.querySelector("[data-md-component=palette]")
|
|
ref.addEventListener("change", function() {
|
|
var palette = __md_get("__palette")
|
|
if (palette && typeof palette.color === "object") {
|
|
var theme = palette.color.scheme === "slate" ? "dark" : "light"
|
|
|
|
/* Instruct Giscus to change theme */
|
|
var frame = document.querySelector(".giscus-frame")
|
|
frame.contentWindow.postMessage(
|
|
{ giscus: { setConfig: { theme } } },
|
|
"https://giscus.app"
|
|
)
|
|
}
|
|
})
|
|
})
|
|
</script> </article> </div> <script>var target=document.getElementById(location.hash.slice(1));target&&target.name&&(target.checked=target.name.startsWith("__tabbed_"))</script> </div> <button type=button class="md-top md-icon" data-md-component=top hidden> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 24 24"><path d="M13 20h-2V8l-5.5 5.5-1.42-1.42L12 4.16l7.92 7.92-1.42 1.42L13 8z"/></svg> Back to top </button> </main> <footer class=md-footer> <div class="md-footer-meta md-typeset"> <div class="md-footer-meta__inner md-grid"> <div class=md-copyright> Made with <a href=https://squidfunk.github.io/mkdocs-material/ target=_blank rel=noopener> Material for MkDocs </a> </div> </div> </div> </footer> </div> <div class=md-dialog data-md-component=dialog> <div class="md-dialog__inner md-typeset"></div> </div> <script id=__config type=application/json>{"base": "../..", "features": ["navigation.instant", "navigation.tracking", "navigation.tabs", "navigation.sections", "navigation.top", "content.action.view", "content.action.edit", "search.suggest", "search.highlight", "content.code.copy"], "search": "../../assets/javascripts/workers/search.6ce7567c.min.js", "translations": {"clipboard.copied": "Copied to clipboard", "clipboard.copy": "Copy to clipboard", "search.result.more.one": "1 more on this page", "search.result.more.other": "# more on this page", "search.result.none": "No matching documents", "search.result.one": "1 matching document", "search.result.other": "# matching documents", "search.result.placeholder": "Type to start searching", "search.result.term.missing": "Missing", "select.version": "Select version"}}</script> <script src=../../assets/javascripts/bundle.83f73b43.min.js></script> </body> </html> |