bash-hackers-wiki/syntax/pe/index.html

196 lines
100 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/pe/ rel=canonical><link href=../pattern/ rel=prev><link href=../quoting/ rel=next><link rel=icon href=../../assets/images/favicon.png><meta name=generator content="mkdocs-1.6.1, mkdocs-material-9.5.40"><title>Parameter expansion - The Bash Hackers Wiki</title><link rel=stylesheet href=../../assets/stylesheets/main.8c3ca2c6.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=#parameter-expansion 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> Parameter expansion </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> <a href=../arrays/ class=md-nav__link> <span class=md-ellipsis> Arrays </span> </a> </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 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> Parameter expansion </span> <span class="md-nav__icon md-icon"></span> </label> <a href=./ class="md-nav__link md-nav__link--active"> <span class=md-ellipsis> Parameter expansion </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=#introduction class=md-nav__link> <span class=md-ellipsis> Introduction </span> </a> </li> <li class=md-nav__item> <a href=#overview class=md-nav__link> <span class=md-ellipsis> Overview </span> </a> </li> <li class=md-nav__item> <a href=#simple-usage class=md-nav__link> <span class=md-ellipsis> Simple usage </span> </a> <nav class=md-nav aria-label="Simple usage"> <ul class=md-nav__list> <li class=md-nav__item> <a href=#simple-usage-arrays class=md-nav__link> <span class=md-ellipsis> Simple usage: Arrays </span> </a> </li> </ul> </nav> </li> <li class=md-nav__item> <a href=#indirection class=md-nav__link> <span class=md-ellipsis> Indirection </span> </a> </li> <li class=md-nav__item> <a href=#case-modification class=md-nav__link> <span class=md-ellipsis> Case modification </span> </a> <nav class=md-nav aria-label="Case modification"> <ul class=md-nav__list> <li class=md-nav__item> <a href=#case-modification-arrays class=md-nav__link> <span class=md-ellipsis> Case modification: Arrays </span> </a> </li> </ul> </nav> </li> <li class=md-nav__item> <a href=#variable-name-expansion class=md-nav__link> <span class=md-ellipsis> Variable name expansion </span> </a> </li> <li class=md-nav__item> <a href=#substring-removal class=md-nav__link> <span class=md-ellipsis> Substring removal </span> </a> <nav class=md-nav aria-label="Substring removal"> <ul class=md-nav__list> <li class=md-nav__item> <a href=#from-the-beginning class=md-nav__link> <span class=md-ellipsis> From the beginning </span> </a> </li> <li class=md-nav__item> <a href=#from-the-end class=md-nav__link> <span class=md-ellipsis> From the end </span> </a> </li> <li class=md-nav__item> <a href=#common-use class=md-nav__link> <span class=md-ellipsis> Common use </span> </a> </li> <li class=md-nav__item> <a href=#substring-removal-arrays class=md-nav__link> <span class=md-ellipsis> Substring removal: Arrays </span> </a> </li> </ul> </nav> </li> <li class=md-nav__item> <a href=#search-and-replace class=md-nav__link> <span class=md-ellipsis> Search and replace </span> </a> <nav class=md-nav aria-label="Search and replace"> <ul class=md-nav__list> <li class=md-nav__item> <a href=#search-and-replace-arrays class=md-nav__link> <span class=md-ellipsis> Search and replace: Arrays </span> </a> </li> </ul> </nav> </li> <li class=md-nav__item> <a href=#string-length class=md-nav__link> <span class=md-ellipsis> String length </span> </a> <nav class=md-nav aria-label="String length"> <ul class=md-nav__list> <li class=md-nav__item> <a href=#string-length-arrays class=md-nav__link> <span class=md-ellipsis> (String) length: Arrays </span> </a> </li> </ul> </nav> </li> <li class=md-nav__item> <a href=#substring-expansion class=md-nav__link> <span class=md-ellipsis> Substring expansion </span> </a> <nav class=md-nav aria-label="Substring expansion"> <ul class=md-nav__list> <li class=md-nav__item> <a href=#using-only-offset class=md-nav__link> <span class=md-ellipsis> Using only Offset </span> </a> </li> <li class=md-nav__item> <a href=#using-offset-and-length class=md-nav__link> <span class=md-ellipsis> Using Offset and Length </span> </a> </li> <li class=md-nav__item> <a href=#negative-offset-value class=md-nav__link> <span class=md-ellipsis> Negative Offset Value </span> </a> </li> <li class=md-nav__item> <a href=#negative-length-value class=md-nav__link> <span class=md-ellipsis> Negative Length Value </span> </a> </li> <li class=md-nav__item> <a href=#substringelement-expansion-arrays class=md-nav__link> <span class=md-ellipsis> Substring/Element expansion: Arrays </span> </a> </li> </ul> </nav> </li> <li class=md-nav__item> <a href=#use-a-default-value class=md-nav__link> <span class=md-ellipsis> Use a default value </span> </a> <nav class=md-nav aria-label="Use a default value"> <ul class=md-nav__list> <li class=md-nav__item> <a href=#use-a-default-value-arrays class=md-nav__link> <span class=md-ellipsis> Use a default value: Arrays </span> </a> </li> </ul> </nav> </li> <li class=md-nav__item> <a href=#assign-a-default-value class=md-nav__link> <span class=md-ellipsis> Assign a default value </span> </a> <nav class=md-nav aria-label="Assign a default value"> <ul class=md-nav__list> <li class=md-nav__item> <a href=#assign-a-default-value-arrays class=md-nav__link> <span class=md-ellipsis> Assign a default value: Arrays </span> </a> </li> </ul> </nav> </li> <li class=md-nav__item> <a href=#use-an-alternate-value class=md-nav__link> <span class=md-ellipsis> Use an alternate value </span> </a> <nav class=md-nav aria-label="Use an alternate value"> <ul class=md-nav__list> <li class=md-nav__item> <a href=#use-an-alternate-value-arrays class=md-nav__link> <span class=md-ellipsis> Use an alternate value: Arrays </span> </a> </li> </ul> </nav> </li> <li class=md-nav__item> <a href=#display-error-if-null-or-unset class=md-nav__link> <span class=md-ellipsis> Display error if null or unset </span> </a> </li> <li class=md-nav__item> <a href=#code-examples class=md-nav__link> <span class=md-ellipsis> Code examples </span> </a> <nav class=md-nav aria-label="Code examples"> <ul class=md-nav__list> <li class=md-nav__item> <a href=#substring-removal_1 class=md-nav__link> <span class=md-ellipsis> Substring removal </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=#quote-nesting class=md-nav__link> <span class=md-ellipsis> Quote Nesting </span> </a> </li> </ul> </nav> </li> </ul> </nav> </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=#introduction class=md-nav__link> <span class=md-ellipsis> Introduction </span> </a> </li> <li class=md-nav__item> <a href=#overview class=md-nav__link> <span class=md-ellipsis> Overview </span> </a> </li> <li class=md-nav__item> <a href=#simple-usage class=md-nav__link> <span class=md-ellipsis> Simple usage </span> </a> <nav class=md-nav aria-label="Simple usage"> <ul class=md-nav__list> <li class=md-nav__item> <a href=#simple-usage-arrays class=md-nav__link> <span class=md-ellipsis> Simple usage: Arrays </span> </a> </li> </ul> </nav> </li> <li class=md-nav__item> <a href=#indirection class=md-nav__link> <span class=md-ellipsis> Indirection </span> </a> </li> <li class=md-nav__item> <a href=#case-modification class=md-nav__link> <span class=md-ellipsis> Case modification </span> </a> <nav class=md-nav aria-label="Case modification"> <ul class=md-nav__list> <li class=md-nav__item> <a href=#case-modification-arrays class=md-nav__link> <span class=md-ellipsis> Case modification: Arrays </span> </a> </li> </ul> </nav> </li> <li class=md-nav__item> <a href=#variable-name-expansion class=md-nav__link> <span class=md-ellipsis> Variable name expansion </span> </a> </li> <li class=md-nav__item> <a href=#substring-removal class=md-nav__link> <span class=md-ellipsis> Substring removal </span> </a> <nav class=md-nav aria-label="Substring removal"> <ul class=md-nav__list> <li class=md-nav__item> <a href=#from-the-beginning class=md-nav__link> <span class=md-ellipsis> From the beginning </span> </a> </li> <li class=md-nav__item> <a href=#from-the-end class=md-nav__link> <span class=md-ellipsis> From the end </span> </a> </li> <li class=md-nav__item> <a href=#common-use class=md-nav__link> <span class=md-ellipsis> Common use </span> </a> </li> <li class=md-nav__item> <a href=#substring-removal-arrays class=md-nav__link> <span class=md-ellipsis> Substring removal: Arrays </span> </a> </li> </ul> </nav> </li> <li class=md-nav__item> <a href=#search-and-replace class=md-nav__link> <span class=md-ellipsis> Search and replace </span> </a> <nav class=md-nav aria-label="Search and replace"> <ul class=md-nav__list> <li class=md-nav__item> <a href=#search-and-replace-arrays class=md-nav__link> <span class=md-ellipsis> Search and replace: Arrays </span> </a> </li> </ul> </nav> </li> <li class=md-nav__item> <a href=#string-length class=md-nav__link> <span class=md-ellipsis> String length </span> </a> <nav class=md-nav aria-label="String length"> <ul class=md-nav__list> <li class=md-nav__item> <a href=#string-length-arrays class=md-nav__link> <span class=md-ellipsis> (String) length: Arrays </span> </a> </li> </ul> </nav> </li> <li class=md-nav__item> <a href=#substring-expansion class=md-nav__link> <span class=md-ellipsis> Substring expansion </span> </a> <nav class=md-nav aria-label="Substring expansion"> <ul class=md-nav__list> <li class=md-nav__item> <a href=#using-only-offset class=md-nav__link> <span class=md-ellipsis> Using only Offset </span> </a> </li> <li class=md-nav__item> <a href=#using-offset-and-length class=md-nav__link> <span class=md-ellipsis> Using Offset and Length </span> </a> </li> <li class=md-nav__item> <a href=#negative-offset-value class=md-nav__link> <span class=md-ellipsis> Negative Offset Value </span> </a> </li> <li class=md-nav__item> <a href=#negative-length-value class=md-nav__link> <span class=md-ellipsis> Negative Length Value </span> </a> </li> <li class=md-nav__item> <a href=#substringelement-expansion-arrays class=md-nav__link> <span class=md-ellipsis> Substring/Element expansion: Arrays </span> </a> </li> </ul> </nav> </li> <li class=md-nav__item> <a href=#use-a-default-value class=md-nav__link> <span class=md-ellipsis> Use a default value </span> </a> <nav class=md-nav aria-label="Use a default value"> <ul class=md-nav__list> <li class=md-nav__item> <a href=#use-a-default-value-arrays class=md-nav__link> <span class=md-ellipsis> Use a default value: Arrays </span> </a> </li> </ul> </nav> </li> <li class=md-nav__item> <a href=#assign-a-default-value class=md-nav__link> <span class=md-ellipsis> Assign a default value </span> </a> <nav class=md-nav aria-label="Assign a default value"> <ul class=md-nav__list> <li class=md-nav__item> <a href=#assign-a-default-value-arrays class=md-nav__link> <span class=md-ellipsis> Assign a default value: Arrays </span> </a> </li> </ul> </nav> </li> <li class=md-nav__item> <a href=#use-an-alternate-value class=md-nav__link> <span class=md-ellipsis> Use an alternate value </span> </a> <nav class=md-nav aria-label="Use an alternate value"> <ul class=md-nav__list> <li class=md-nav__item> <a href=#use-an-alternate-value-arrays class=md-nav__link> <span class=md-ellipsis> Use an alternate value: Arrays </span> </a> </li> </ul> </nav> </li> <li class=md-nav__item> <a href=#display-error-if-null-or-unset class=md-nav__link> <span class=md-ellipsis> Display error if null or unset </span> </a> </li> <li class=md-nav__item> <a href=#code-examples class=md-nav__link> <span class=md-ellipsis> Code examples </span> </a> <nav class=md-nav aria-label="Code examples"> <ul class=md-nav__list> <li class=md-nav__item> <a href=#substring-removal_1 class=md-nav__link> <span class=md-ellipsis> Substring removal </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=#quote-nesting class=md-nav__link> <span class=md-ellipsis> Quote Nesting </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"> <nav class=md-tags> <a href=../../tags/#bash class=md-tag>bash</a> <a href=../../tags/#shell class=md-tag>shell</a> <a href=../../tags/#scripting class=md-tag>scripting</a> <a href=../../tags/#expansion class=md-tag>expansion</a> <a href=../../tags/#substitution class=md-tag>substitution</a> <a href=../../tags/#text class=md-tag>text</a> <a href=../../tags/#variable class=md-tag>variable</a> <a href=../../tags/#parameter class=md-tag>parameter</a> <a href=../../tags/#mangle class=md-tag>mangle</a> <a href=../../tags/#substitute class=md-tag>substitute</a> <a href=../../tags/#change class=md-tag>change</a> <a href=../../tags/#check class=md-tag>check</a> <a href=../../tags/#defined class=md-tag>defined</a> <a href=../../tags/#null class=md-tag>null</a> <a href=../../tags/#array class=md-tag>array</a> <a href=../../tags/#arrays class=md-tag>arrays</a> </nav> <a href=https://github.com/flokoe/bash-hackers-wiki/edit/main/docs/syntax/pe.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/pe.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=parameter-expansion>Parameter expansion<a class=headerlink href=#parameter-expansion title="Permanent link">&para;</a></h1> <h2 id=introduction>Introduction<a class=headerlink href=#introduction title="Permanent link">&para;</a></h2> <p>One core functionality of Bash is to manage <strong>parameters</strong>. A parameter is an entity that stores values and is referenced by a <strong>name</strong>, a <strong>number</strong> or a <strong>special symbol</strong>.</p> <ul> <li>parameters referenced by a name are called <strong>variables</strong> (this also applies to <a href=../arrays/ >arrays</a>)</li> <li>parameters referenced by a number are called <strong>positional parameters</strong> and reflect the arguments given to a shell</li> <li>parameters referenced by a <strong>special symbol</strong> are auto-set parameters that have different special meanings and uses</li> </ul> <p><strong>Parameter expansion</strong> is the procedure to get the value from the referenced entity, like expanding a variable to print its value. On expansion time you can do very nasty things with the parameter or its value. These things are described here.</p> <p><strong>If you saw</strong> some parameter expansion syntax somewhere, and need to check what it can be, try the overview section below!</p> <p><strong>Arrays</strong> can be special cases for parameter expansion, every applicable description mentions arrays below. Please also see the <a href=../arrays/ >article about arrays</a>.</p> <p>For a more technical view what a parameter is and which types exist, <a href=../../dict/parameter/ >see the dictionary entry for "parameter"</a>.</p> <h2 id=overview>Overview<a class=headerlink href=#overview title="Permanent link">&para;</a></h2> <p>Looking for a specific syntax you saw, without knowing the name?</p> <ul> <li><a href=#simple_usage>Simple usage</a><ul> <li><code>$PARAMETER</code></li> <li><code>${PARAMETER}</code></li> </ul> </li> <li><a href=#indirection>Indirection</a><ul> <li><code>${!PARAMETER}</code></li> </ul> </li> <li><a href=#case_modification>Case modification</a><ul> <li><code>${PARAMETER^}</code></li> <li><code>${PARAMETER^^}</code></li> <li><code>${PARAMETER,}</code></li> <li><code>${PARAMETER,,}</code></li> <li><code>${PARAMETER~}</code></li> <li><code>${PARAMETER~~}</code></li> </ul> </li> <li><a href=#variable_name_expansion>Variable name expansion</a><ul> <li><code>${!PREFIX*}</code></li> <li><code>${!PREFIX@}</code></li> </ul> </li> <li><a href=#substring_removal>Substring removal</a> (also for <strong>filename manipulation</strong>!)<ul> <li><code>${PARAMETER#PATTERN}</code></li> <li><code>${PARAMETER##PATTERN}</code></li> <li><code>${PARAMETER%PATTERN}</code></li> <li><code>${PARAMETER%%PATTERN}</code></li> </ul> </li> <li><a href=#search_and_replace>Search and replace</a><ul> <li><code>${PARAMETER/PATTERN/STRING}</code></li> <li><code>${PARAMETER//PATTERN/STRING}</code></li> <li><code>${PARAMETER/PATTERN}</code></li> <li><code>${PARAMETER//PATTERN}</code></li> </ul> </li> <li><a href=#string_length>String length</a><ul> <li><code>${#PARAMETER}</code></li> </ul> </li> <li><a href=#substring_expansion>Substring expansion</a><ul> <li><code>${PARAMETER:OFFSET}</code></li> <li><code>${PARAMETER:OFFSET:LENGTH}</code></li> </ul> </li> <li><a href=#use_a_default_value>Use a default value</a><ul> <li><code>${PARAMETER:-WORD}</code></li> <li><code>${PARAMETER-WORD}</code></li> </ul> </li> <li><a href=#assign_a_default_value>Assign a default value</a><ul> <li><code>${PARAMETER:=WORD}</code></li> <li><code>${PARAMETER=WORD}</code></li> </ul> </li> <li><a href=#use_an_alternate_value>Use an alternate value</a><ul> <li><code>${PARAMETER:+WORD}</code></li> <li><code>${PARAMETER+WORD}</code></li> </ul> </li> <li><a href=#display_error_if_null_or_unset>Display error if null or unset</a><ul> <li><code>${PARAMETER:?WORD}</code></li> <li><code>${PARAMETER?WORD}</code></li> </ul> </li> </ul> <h2 id=simple-usage>Simple usage<a class=headerlink href=#simple-usage title="Permanent link">&para;</a></h2> <p><code>$PARAMETER</code></p> <p><code>${PARAMETER}</code></p> <p>The easiest form is to just use a parameter's name within braces. This is identical to using <code>$FOO</code> like you see it everywhere, but has the advantage that it can be immediately followed by characters that would be interpreted as part of the parameter name otherwise. Compare these two expressions (<code>WORD="car"</code> for example), where we want to print a word with a trailing "s":</p> <div class=highlight><pre><span></span><code>echo &quot;The plural of $WORD is most likely $WORDs&quot;
echo &quot;The plural of $WORD is most likely ${WORD}s&quot;
</code></pre></div> <p><u>Why does the first one fail?</u> It prints nothing, because a parameter (variable) named "<code>WORDs</code>" is undefined and thus printed as "" (<em>nothing</em>). Without using braces for parameter expansion, Bash will interpret the sequence of all valid characters from the introducing "<code>$</code>" up to the last valid character as name of the parameter. When using braces you just force Bash to <strong>only interpret the name inside your braces</strong>.</p> <p>Also, please remember, that <strong>parameter names are</strong> (like nearly everything in UNIX&reg;) <strong>case sensitive!</strong></p> <p>The second form with the curly braces is also needed to access positional parameters (arguments to a script) beyond <code>$9</code>:</p> <div class=highlight><pre><span></span><code>echo &quot;Argument 1 is: $1&quot;
echo &quot;Argument 10 is: ${10}&quot;
</code></pre></div> <h3 id=simple-usage-arrays>Simple usage: Arrays<a class=headerlink href=#simple-usage-arrays title="Permanent link">&para;</a></h3> <p>See also the <a href=../arrays/ >article about general array syntax</a></p> <p>For arrays you always need the braces. The arrays are expanded by individual indexes or mass arguments. An individual index behaves like a normal parameter, for the mass expansion, please read the article about arrays linked above.</p> <ul> <li><code>${array[5]}</code></li> <li><code>${array[*]}</code></li> <li><code>${array[@]}</code></li> </ul> <h2 id=indirection>Indirection<a class=headerlink href=#indirection title="Permanent link">&para;</a></h2> <p><code>${!PARAMETER}</code></p> <p>In some cases, like for example</p> <div class=highlight><pre><span></span><code>${PARAMETER}
${PARAMETER:0:3}
</code></pre></div> <p>you can instead use the form</p> <div class=highlight><pre><span></span><code>${!PARAMETER}
</code></pre></div> <p>to enter a level of indirection. The referenced parameter is not <code>PARAMETER</code> itself, but the parameter whose name is stored as the value of <code>PARAMETER</code>. If the parameter <code>PARAMETER</code> has the value "<code>TEMP</code>", then <code>${!PARAMETER}</code> will expand to the value of the parameter named <code>TEMP</code>:</p> <div class=highlight><pre><span></span><code>read -rep &#39;Which variable do you want to inspect? &#39; look_var
printf &#39;The value of &quot;%s&quot; is: &quot;%s&quot;\n&#39; &quot;$look_var&quot; &quot;${!look_var}&quot;
</code></pre></div> <p>Of course the indirection also works with special variables:</p> <div class=highlight><pre><span></span><code># set some fake positional parameters
set one two three four
# get the LAST argument (&quot;#&quot; stores the number of arguments, so &quot;!#&quot; will reference the LAST argument)
echo ${!#}
</code></pre></div> <p>You can think of this mechanism as being roughly equivalent to taking any parameter expansion that begins with the parameter name, and substituting the <code>!PARAMETER</code> part with the value of PARAMETER.</p> <div class=highlight><pre><span></span><code>echo &quot;${!var^^}&quot;
# ...is equivalent to
eval &#39;echo &quot;${&#39;&quot;$var&quot;&#39;^^}&quot;&#39;
</code></pre></div> <p>It was an unfortunate design decision to use the <code>!</code> prefix for indirection, as it introduces parsing ambiguity with other parameter expansions that begin with <code>!</code>. Indirection is not possible in combination with any parameter expansion whose modifier requires a prefix to the parameter name. Specifically, indirection isn't possible on the <code>${!var@}</code>, <code>${!var*}</code>, <code>${!var[@]}</code>, <code>${!var[*]}</code>, and <code>${#var}</code> forms. This means the <code>!</code> prefix can't be used to retrieve the indices of an array, the length of a string, or number of elements in an array indirectly (see <a href=../arrays/#indirection>syntax/arrays#indirection</a> for workarounds). Additionally, the <code>!</code>-prefixed parameter expansion conflicts with ksh-like shells which have the more powerful "name-reference" form of indirection, where the exact same syntax is used to expand to the name of the variable being referenced.</p> <p>Indirect references to <a href=../arrays/ >array names</a> are also possible since the Bash 3 series (exact version unknown), but undocumented. See <a href=../arrays/#indirection>syntax/arrays#indirection</a> for details.</p> <p>Chet has added an initial implementation of the ksh <code>nameref</code> declaration command to the git devel branch. (<code>declare -n</code>, <code>local -n</code>, etc, will be supported). This will finally address many issues around passing and returning complex datatypes to/from functions.</p> <h2 id=case-modification>Case modification<a class=headerlink href=#case-modification title="Permanent link">&para;</a></h2> <p><code>${PARAMETER^}</code></p> <p><code>${PARAMETER^^}</code></p> <p><code>${PARAMETER,}</code></p> <p><code>${PARAMETER,,}</code></p> <p><code>${PARAMETER~}</code></p> <p><code>${PARAMETER~~}</code></p> <p>These expansion operators modify the case of the letters in the expanded text.</p> <p>The <code>^</code> operator modifies the first character to uppercase, the <code>,</code> operator to lowercase. When using the double-form (<code>^^</code> and <code>,,</code>), all characters are converted.</p> <p><wrap center round info 60%></p> <p>The (<strong>currently undocumented</strong>) operators <code>~</code> and <code>~~</code> reverse the case of the given text (in <code>PARAMETER</code>).<code>~</code> reverses the case of first letter of words in the variable while <code>~~</code> reverses case for all. Thanks to <code>Bushmills</code> and <code>geirha</code> on the Freenode IRC channel for this finding.</p> <p></wrap></p> <p><u><strong>Example: Rename all <code>*.txt</code> filenames to lowercase</strong></u></p> <div class=highlight><pre><span></span><code>for file in *.txt; do
mv &quot;$file&quot; &quot;${file,,}&quot;
done
</code></pre></div> <p><u><strong>Note:</strong></u> Case modification is a handy feature you can apply to a name or a title. Or is it? Case modification was an important aspect of the Bash 4 release. Bash version 4, RC1 would perform word splitting, and then case modification, resulting in title case (where every word is capitalized). It was decided to apply case modification to values, not words, for the Bash 4 release. Thanks Chet.</p> <h3 id=case-modification-arrays>Case modification: Arrays<a class=headerlink href=#case-modification-arrays title="Permanent link">&para;</a></h3> <p>Case modification can be used to create the proper capitalization for names or titles. Just assign it to an array:</p> <p><code>declare -a title=(my hello world john smith)</code></p> <p>For <a href=../arrays/ >array</a> expansion, the case modification applies to <strong>every expanded element, no matter if you expand an individual index or mass-expand</strong> the whole array using <code>@</code> or <code>*</code> subscripts. Some examples:</p> <p>Assume: <code>array=(This is some Text)</code></p> <ul> <li><code>echo "${array[@],}"</code><ul> <li>=&gt; <code>this is some text</code></li> </ul> </li> <li><code>echo "${array[@],,}"</code><ul> <li>=&gt; <code>this is some text</code></li> </ul> </li> <li><code>echo "${array[@]^}"</code><ul> <li>=&gt; <code>This Is Some Text</code></li> </ul> </li> <li> <p><code>echo "${array[@]^^}"</code></p> <ul> <li> <p>=&gt; <code>THIS IS SOME TEXT</code></p> </li> <li> <p>''echo "${array[2]^^}"''</p> </li> <li>=&gt; ''SOME''</li> </ul> </li> </ul> <h2 id=variable-name-expansion>Variable name expansion<a class=headerlink href=#variable-name-expansion title="Permanent link">&para;</a></h2> <p><code>${!PREFIX*}</code></p> <p><code>${!PREFIX@}</code></p> <p>This expands to a list of all set <strong>variable names</strong> beginning with the string <code>PREFIX</code>. The elements of the list are separated by the first character in the <code>IFS</code>-variable (<space> by default).</p> <p>This will show all defined variable names (not values!) beginning with "BASH":</p> <div class=highlight><pre><span></span><code>$ echo ${!BASH*}
BASH BASH_ARGC BASH_ARGV BASH_COMMAND BASH_LINENO BASH_SOURCE BASH_SUBSHELL BASH_VERSINFO BASH_VERSION
</code></pre></div> <p>This list will also include <a href=../arrays/ >array names</a>.</p> <h2 id=substring-removal>Substring removal<a class=headerlink href=#substring-removal title="Permanent link">&para;</a></h2> <p><code>${PARAMETER#PATTERN}</code></p> <p><code>${PARAMETER##PATTERN}</code></p> <p><code>${PARAMETER%PATTERN}</code></p> <p><code>${PARAMETER%%PATTERN}</code></p> <p>This one can <strong>expand only a part</strong> of a parameter's value, <strong>given a pattern to describe what to remove</strong> from the string. The pattern is interpreted just like a pattern to describe a filename to match (globbing). See <a href=../pattern/ >Pattern matching</a> for more.</p> <p>Example string (<em>just a quote from a big man</em>):</p> <div class=highlight><pre><span></span><code>MYSTRING=&quot;Be liberal in what you accept, and conservative in what you send&quot;
</code></pre></div> <h3 id=from-the-beginning>From the beginning<a class=headerlink href=#from-the-beginning title="Permanent link">&para;</a></h3> <p><code>${PARAMETER#PATTERN}</code> and <code>${PARAMETER##PATTERN}</code></p> <p>This form is to remove the described <a href=../pattern/ >pattern</a> trying to <strong>match it from the beginning of the string</strong>. The operator "<code>#</code>" will try to remove the shortest text matching the pattern, while "<code>##</code>" tries to do it with the longest text matching. Look at the following examples to get the idea (matched text ~~marked striked~~, remember it will be removed!):</p> <p>Syntax Result</p> <hr> <p><code>${MYSTRING#*in}</code> ~~Be liberal in~~ what you accept, and conservative in what you send <code>${MYSTRING##*in}</code> ~~Be liberal in what you accept, and conservative in~~ what you send</p> <h3 id=from-the-end>From the end<a class=headerlink href=#from-the-end title="Permanent link">&para;</a></h3> <p><code>${PARAMETER%PATTERN}</code> and <code>${PARAMETER%%PATTERN}</code></p> <p>In the second form everything will be the same, except that Bash now tries to match the pattern from the end of the string:</p> <p>Syntax Result</p> <hr> <p><code>${MYSTRING%in*}</code> Be liberal in what you accept, and conservative ~~in what you send~~ <code>${MYSTRING%%in*}</code> Be liberal ~~in what you accept, and conservative in what you send~~</p> <p>The second form nullifies variables that begin with <code>in</code>, by working from the end.</p> <h3 id=common-use>Common use<a class=headerlink href=#common-use title="Permanent link">&para;</a></h3> <p><u><strong>How the heck does that help to make my life easier?</strong></u></p> <p>Well, maybe the most common use for it is to <strong>extract parts of a filename</strong>. Just look at the following list with examples:</p> <ul> <li><strong>Get name without extension</strong><ul> <li><code>${FILENAME%.*}</code></li> <li>=&gt; <code>bash_hackers.txt</code></li> </ul> </li> <li><strong>Get extension</strong><ul> <li><code>${FILENAME##*.}</code></li> <li>=&gt; <code>bash_hackers.txt</code></li> </ul> </li> <li><strong>Get directory name</strong><ul> <li><code>${PATHNAME%/*}</code></li> <li>=&gt; <code>/home/bash/bash_hackers.txt</code></li> </ul> </li> <li><strong>Get filename</strong><ul> <li><code>${PATHNAME##*/}</code></li> <li>=&gt; <code>/home/bash/bash_hackers.txt</code></li> </ul> </li> </ul> <p>These are the syntaxes for filenames with a single extension. Depending on your needs, you might need to adjust shortest/longest match.</p> <h3 id=substring-removal-arrays>Substring removal: Arrays<a class=headerlink href=#substring-removal-arrays title="Permanent link">&para;</a></h3> <p>As for most parameter expansion features, working on <a href=../arrays/ >arrays</a> <strong>will handle each expanded element</strong>, for individual expansion and also for mass expansion.</p> <p>Simple example, removing a trailing <code>is</code> from all array elements (on expansion):</p> <p>Assume: <code>array=(This is a text)</code></p> <ul> <li><code>echo "${array[@]%is}"</code><ul> <li>=&gt; <code>Th a text</code></li> <li>(it was: <code>This is a text</code>)</li> </ul> </li> </ul> <p>All other variants of this expansion behave the same.</p> <h2 id=search-and-replace>Search and replace<a class=headerlink href=#search-and-replace title="Permanent link">&para;</a></h2> <p><code>${PARAMETER/PATTERN/STRING}</code></p> <p><code>${PARAMETER//PATTERN/STRING}</code></p> <p><code>${PARAMETER/PATTERN}</code></p> <p><code>${PARAMETER//PATTERN}</code></p> <p>This one can substitute (<em>replace</em>) a substring <a href=../pattern/ >matched by a pattern</a>, on expansion time. The matched substring will be entirely removed and the given string will be inserted. Again some example string for the tests:</p> <div class=highlight><pre><span></span><code>MYSTRING=&quot;Be liberal in what you accept, and conservative in what you send&quot;
</code></pre></div> <p>The two main forms only differ in <strong>the number of slashes</strong> after the parameter name: <code>${PARAMETER/PATTERN/STRING}</code> and <code>${PARAMETER//PATTERN/STRING}</code></p> <p>The first one (<em>one slash</em>) is to only substitute <strong>the first occurrence</strong> of the given pattern, the second one (<em>two slashes</em>) is to substitute <strong>all occurrences</strong> of the pattern.</p> <p>First, let's try to say "happy" instead of "conservative" in our example string:</p> <div class=highlight><pre><span></span><code>${MYSTRING//conservative/happy}
</code></pre></div> <p>=&gt; <code>Be liberal in what you accept, and conservativehappy in what you send</code></p> <p>Since there is only one "conservative" in that example, it really doesn't matter which of the two forms we use.</p> <p>Let's play with the word "in", I don't know if it makes any sense, but let's substitute it with "by".</p> <p><u><strong>First form: Substitute first occurrence</strong></u></p> <div class=highlight><pre><span></span><code>${MYSTRING/in/by}
</code></pre></div> <p>=&gt; <code>Be liberal inby what you accept, and conservative in what you send</code></p> <p><u><strong>Second form: Substitute all occurrences</strong></u></p> <div class=highlight><pre><span></span><code>${MYSTRING//in/by}
</code></pre></div> <p>=&gt; <code>Be liberal inby what you accept, and conservative inby what you send</code></p> <p><u><strong>Anchoring</strong></u> Additionally you can "anchor" an expression: A <code>#</code> (hashmark) will indicate that your expression is matched against the beginning portion of the string, a <code>%</code> (percent-sign) will do it for the end portion.</p> <div class=highlight><pre><span></span><code>MYSTRING=xxxxxxxxxx
echo ${MYSTRING/#x/y} # RESULT: yxxxxxxxxx
echo ${MYSTRING/%x/y} # RESULT: xxxxxxxxxy
</code></pre></div> <p>If the replacement part is completely omitted, the matches are replaced by the nullstring, i.e., they are removed. This is equivalent to specifying an empty replacement:</p> <div class=highlight><pre><span></span><code>echo ${MYSTRING//conservative/}
# is equivalent to
echo ${MYSTRING//conservative}
</code></pre></div> <h3 id=search-and-replace-arrays>Search and replace: Arrays<a class=headerlink href=#search-and-replace-arrays title="Permanent link">&para;</a></h3> <p>This parameter expansion type applied to <a href=../arrays/ >arrays</a> <strong>applies to all expanded elements</strong>, no matter if an individual element is expanded, or all elements using the mass expansion syntaxes.</p> <p>A simple example, changing the (lowercase) letter <code>t</code> to <code>d</code>:</p> <p>Assume: <code>array=(This is a text)</code></p> <ul> <li><code>echo "${array[@]/t/d}"</code><ul> <li>=&gt; <code>This is a dext</code></li> </ul> </li> <li><code>echo "${array[@]//t/d}"</code><ul> <li>=&gt; <code>This is a dexd</code></li> </ul> </li> </ul> <h2 id=string-length>String length<a class=headerlink href=#string-length title="Permanent link">&para;</a></h2> <p><code>${#PARAMETER}</code></p> <p>When you use this form, the length of the parameter's value is expanded. Again, a quote from a big man, to have a test text:</p> <div class=highlight><pre><span></span><code>MYSTRING=&quot;Be liberal in what you accept, and conservative in what you send&quot;
</code></pre></div> <p>Using echo <code>${#MYSTRING}</code>...</p> <p>=&gt; <code>64</code></p> <p>The length is reported in characters, not in bytes. Depending on your environment this may not always be the same (multibyte-characters, like in UTF8 encoding).</p> <p>There's not much to say about it, mh?</p> <h3 id=string-length-arrays>(String) length: Arrays<a class=headerlink href=#string-length-arrays title="Permanent link">&para;</a></h3> <p>For <a href=../arrays/ >arrays</a>, this expansion type has two meanings:</p> <ul> <li>For <strong>individual</strong> elements, it reports the string length of the element (as for every "normal" parameter)</li> <li>For the <strong>mass subscripts</strong> <code>@</code> and <code>*</code> it reports the number of set elements in the array</li> </ul> <p>Example:</p> <p>Assume: <code>array=(This is a text)</code></p> <ul> <li><code>echo ${#array[1]}</code><ul> <li>=&gt; 2 (the word "is" has a length of 2)</li> </ul> </li> <li><code>echo ${#array[@]}</code><ul> <li>=&gt; 4 (the array contains 4 elements)</li> </ul> </li> </ul> <p><u><strong>Attention:</strong></u> The number of used elements does not need to conform to the highest index. Sparse arrays are possible in Bash, that means you can have 4 elements, but with indexes 1, 7, 20, 31. <strong>You can't loop through such an array with a counter loop based on the number of elements!</strong></p> <h2 id=substring-expansion>Substring expansion<a class=headerlink href=#substring-expansion title="Permanent link">&para;</a></h2> <p><code>${PARAMETER:OFFSET}</code></p> <p><code>${PARAMETER:OFFSET:LENGTH}</code></p> <p>This one can expand only a <strong>part</strong> of a parameter's value, given a <strong>position to start</strong> and maybe a <strong>length</strong>. If <code>LENGTH</code> is omitted, the parameter will be expanded up to the end of the string. If <code>LENGTH</code> is negative, it's taken as a second offset into the string, counting from the end of the string.</p> <p><code>OFFSET</code> and <code>LENGTH</code> can be <strong>any</strong> <a href=../arith_expr/ >arithmetic expression</a>. <strong>Take care:</strong> The <code>OFFSET</code> starts at 0, not at 1!</p> <p>Example string (a quote from a big man): <code>MYSTRING="Be liberal in what you accept, and conservative in what you send"</code></p> <h3 id=using-only-offset>Using only Offset<a class=headerlink href=#using-only-offset title="Permanent link">&para;</a></h3> <p>In the first form, the expansion is used without a length value, note that the offset 0 is the first character:</p> <div class=highlight><pre><span></span><code>echo ${MYSTRING:35}
</code></pre></div> <p>=&gt; <code>&lt;del&gt;Be liberal in what you accept, and &lt;/del&gt;conservative in what you send</code></p> <h3 id=using-offset-and-length>Using Offset and Length<a class=headerlink href=#using-offset-and-length title="Permanent link">&para;</a></h3> <p>In the second form we also give a length value:</p> <div class=highlight><pre><span></span><code>echo ${MYSTRING:35:12}
</code></pre></div> <p>=&gt; <code>&lt;del&gt;Be liberal in what you accept, and &lt;/del&gt;conservative&lt;del&gt; in what you send&lt;/del&gt;</code></p> <h3 id=negative-offset-value>Negative Offset Value<a class=headerlink href=#negative-offset-value title="Permanent link">&para;</a></h3> <p>If the given offset is negative, it's counted from the end of the string, i.e. an offset of -1 is the last character. In that case, the length still counts forward, of course. One special thing is to do when using a negative offset: You need to separate the (negative) number from the colon:</p> <div class=highlight><pre><span></span><code>${MYSTRING: -10:5}
${MYSTRING:(-10):5}
</code></pre></div> <p>Why? Because it's interpreted as the parameter expansion syntax to <a href=./#use_a_default_value>use a default value</a>.</p> <h3 id=negative-length-value>Negative Length Value<a class=headerlink href=#negative-length-value title="Permanent link">&para;</a></h3> <p>If the <code>LENGTH</code> value is negative, it's used as offset from the end of the string. The expansion happens from the first to the second offset then:</p> <div class=highlight><pre><span></span><code>echo &quot;${MYSTRING:11:-17}&quot;
</code></pre></div> <p>=&gt; <code>&lt;del&gt;Be liberal &lt;/del&gt;in what you accept, and conservative&lt;del&gt; in what you send&lt;/del&gt;</code></p> <p>This works since Bash 4.2-alpha, see also <a href=../../scripting/bashchanges/ >bashchanges</a>.</p> <h3 id=substringelement-expansion-arrays>Substring/Element expansion: Arrays<a class=headerlink href=#substringelement-expansion-arrays title="Permanent link">&para;</a></h3> <p>For <a href=../arrays/ >arrays</a>, this expansion type has again 2 meanings:</p> <ul> <li>For <strong>individual</strong> elements, it expands to the specified substring (as for every "normal" parameter)</li> <li>For the <strong>mass subscripts</strong> <code>@</code> and <code>*</code> it mass-expands individual array elements denoted by the 2 numbers given (<em>starting element</em>, <em>number of elements</em>)</li> </ul> <p>Example:</p> <p>Assume: <code>array=(This is a text)</code></p> <ul> <li><code>echo ${array[0]:2:2}</code><ul> <li>=&gt; <code>is</code> (the "is" in "This", array element 0)</li> </ul> </li> <li><code>echo ${array[@]:1:2}</code><ul> <li>=&gt; <code>is a</code> (from element 1 inclusive, 2 elements are expanded, i.e. element 1 and 2)</li> </ul> </li> </ul> <h2 id=use-a-default-value>Use a default value<a class=headerlink href=#use-a-default-value title="Permanent link">&para;</a></h2> <p><code>${PARAMETER:-WORD}</code></p> <p><code>${PARAMETER-WORD}</code></p> <p>If the parameter <code>PARAMETER</code> is unset (never was defined) or null (empty), this one expands to <code>WORD</code>, otherwise it expands to the value of <code>PARAMETER</code>, as if it just was <code>${PARAMETER}</code>. If you omit the <code>:</code> (colon), like shown in the second form, the default value is only used when the parameter was <strong>unset</strong>, not when it was empty.</p> <div class=highlight><pre><span></span><code>echo &quot;Your home directory is: ${HOME:-/home/$USER}.&quot;
echo &quot;${HOME:-/home/$USER} will be used to store your personal data.&quot;
</code></pre></div> <p>If <code>HOME</code> is unset or empty, everytime you want to print something useful, you need to put that parameter syntax in.</p> <div class=highlight><pre><span></span><code>#!/bin/bash
read -p &quot;Enter your gender (just press ENTER to not tell us): &quot; GENDER
echo &quot;Your gender is ${GENDER:-a secret}.&quot;
</code></pre></div> <p>It will print "Your gender is a secret." when you don't enter the gender. Note that the default value is <strong>used on expansion time</strong>, it is <strong>not assigned to the parameter</strong>.</p> <h3 id=use-a-default-value-arrays>Use a default value: Arrays<a class=headerlink href=#use-a-default-value-arrays title="Permanent link">&para;</a></h3> <p>For <a href=../arrays/ >arrays</a>, the behaviour is very similar. Again, you have to make a difference between expanding an individual element by a given index and mass-expanding the array using the <code>@</code> and <code>*</code> subscripts.</p> <ul> <li>For individual elements, it's the very same: If the expanded element is <code>NULL</code> or unset (watch the <code>:-</code> and <code>-</code> variants), the default text is expanded</li> <li>For mass-expansion syntax, the default text is expanded if the array<ul> <li>contains no element or is unset (the <code>:-</code> and <code>-</code> variants mean the <strong>same</strong> here)</li> <li>contains only elements that are the nullstring (the <code>:-</code> variant)</li> </ul> </li> </ul> <p>In other words: The basic meaning of this expansion type is applied as consistent as possible to arrays.</p> <p>Example code (please try the example cases yourself):</p> <div class=highlight><pre><span></span><code>####
# Example cases for unset/empty arrays and nullstring elements
####
### CASE 1: Unset array (no array)
# make sure we have no array at all
unset array
echo ${array[@]:-This array is NULL or unset}
echo ${array[@]-This array is NULL or unset}
### CASE 2: Set but empty array (no elements)
# declare an empty array
array=()
echo ${array[@]:-This array is NULL or unset}
echo ${array[@]-This array is NULL or unset}
### CASE 3: An array with only one element, a nullstring
array=(&quot;&quot;)
echo ${array[@]:-This array is NULL or unset}
echo ${array[@]-This array is NULL or unset}
### CASE 4: An array with only two elements, a nullstring and a normal word
array=(&quot;&quot; word)
echo ${array[@]:-This array is NULL or unset}
echo ${array[@]-This array is NULL or unset}
</code></pre></div> <h2 id=assign-a-default-value>Assign a default value<a class=headerlink href=#assign-a-default-value title="Permanent link">&para;</a></h2> <p><code>${PARAMETER:=WORD}</code></p> <p><code>${PARAMETER=WORD}</code></p> <p>This one works like the <a href=./#use_a_default_value>using default values</a>, but the default text you give is not only expanded, but also <strong>assigned</strong> to the parameter, if it was unset or null. Equivalent to using a default value, when you omit the <code>:</code> (colon), as shown in the second form, the default value will only be assigned when the parameter was <strong>unset</strong>.</p> <div class=highlight><pre><span></span><code>echo &quot;Your home directory is: ${HOME:=/home/$USER}.&quot;
echo &quot;$HOME will be used to store your personal data.&quot;
</code></pre></div> <p>After the first expansion here (<code>${HOME:=/home/$USER}</code>), <code>HOME</code> is set and usable.</p> <p>Let's change our code example from above:</p> <div class=highlight><pre><span></span><code>#!/bin/bash
read -p &quot;Enter your gender (just press ENTER to not tell us): &quot; GENDER
echo &quot;Your gender is ${GENDER:=a secret}.&quot;
echo &quot;Ah, in case you forgot, your gender is really: $GENDER&quot;
</code></pre></div> <h3 id=assign-a-default-value-arrays>Assign a default value: Arrays<a class=headerlink href=#assign-a-default-value-arrays title="Permanent link">&para;</a></h3> <p>For <a href=../arrays/ >arrays</a> this expansion type is limited. For an individual index, it behaves like for a "normal" parameter, the default value is assigned to this one element. The mass-expansion subscripts <code>@</code> and <code>*</code> <strong>can not be used here</strong> because it's not possible to assign to them!</p> <h2 id=use-an-alternate-value>Use an alternate value<a class=headerlink href=#use-an-alternate-value title="Permanent link">&para;</a></h2> <p><code>${PARAMETER:+WORD}</code></p> <p><code>${PARAMETER+WORD}</code></p> <p>This form expands to nothing if the parameter is unset or empty. If it is set, it does not expand to the parameter's value, <strong>but to some text you can specify</strong>:</p> <div class=highlight><pre><span></span><code>echo &quot;The Java application was installed and can be started.${JAVAPATH:+ NOTE: JAVAPATH seems to be set}&quot;
</code></pre></div> <p>The above code will simply add a warning if <code>JAVAPATH</code> is set (because it could influence the startup behaviour of that imaginary application).</p> <p>Some more unrealistic example... Ask for some flags (for whatever reason), and then, if they were set, print a warning and also print the flags:</p> <div class=highlight><pre><span></span><code>#!/bin/bash
read -p &quot;If you want to use special flags, enter them now: &quot; SPECIAL_FLAGS
echo &quot;The installation of the application is finished${SPECIAL_FLAGS:+ (NOTE: there are special flags set: $SPECIAL_FLAGS)}.&quot;
</code></pre></div> <p>If you omit the colon, as shown in the second form (<code>${PARAMETER+WORD}</code>), the alternate value will be used if the parameter is set (and it can be empty)! You can use it, for example, to complain if variables you need (and that can be empty) are undefined:</p> <div class=highlight><pre><span></span><code># test that with the three stages:
# unset foo
# foo=&quot;&quot;
# foo=&quot;something&quot;
if [[ ${foo+isset} = isset ]]; then
echo &quot;foo is set...&quot;
else
echo &quot;foo is not set...&quot;
fi
</code></pre></div> <h3 id=use-an-alternate-value-arrays>Use an alternate value: Arrays<a class=headerlink href=#use-an-alternate-value-arrays title="Permanent link">&para;</a></h3> <p>Similar to the cases for <a href=../arrays/ >arrays</a> to expand to a default value, this expansion behaves like for a "normal" parameter when using individual array elements by index, but reacts differently when using the mass-expansion subscripts <code>@</code> and <code>*</code>:</p> <div class=highlight><pre><span></span><code> * For individual elements, it&#39;s the very same: If the expanded element is **not** NULL or unset (watch the :+ and + variants), the alternate text is expanded
* For mass-expansion syntax, the alternate text is expanded if the array
* contains elements where min. one element is **not** a nullstring (the :+ and + variants mean the same here)
* contains **only** elements that are **not** the nullstring (the :+ variant)
</code></pre></div> <p>For some cases to play with, please see the code examples in the <a href=#use_a_default_valuearrays>description for using a default value</a>.</p> <h2 id=display-error-if-null-or-unset>Display error if null or unset<a class=headerlink href=#display-error-if-null-or-unset title="Permanent link">&para;</a></h2> <p><code>${PARAMETER:?WORD}</code></p> <p><code>${PARAMETER?WORD}</code></p> <p>If the parameter <code>PARAMETER</code> is set/non-null, this form will simply expand it. Otherwise, the expansion of <code>WORD</code> will be used as appendix for an error message:</p> <div class=highlight><pre><span></span><code>$ echo &quot;The unset parameter is: ${p_unset?not set}&quot;
bash: p_unset: not set
</code></pre></div> <p>After printing this message,</p> <ul> <li>an interactive shell has <code>$?</code> to a non-zero value</li> <li>a non-interactive shell exits with a non-zero exit code</li> </ul> <p>The meaning of the colon (<code>:</code>) is the same as for the other parameter expansion syntaxes: It specifies if</p> <ul> <li>only unset or</li> <li>unset and empty parameters</li> </ul> <p>are taken into account.</p> <h2 id=code-examples>Code examples<a class=headerlink href=#code-examples title="Permanent link">&para;</a></h2> <h3 id=substring-removal_1>Substring removal<a class=headerlink href=#substring-removal_1 title="Permanent link">&para;</a></h3> <p>Removing the first 6 characters from a text string:</p> <div class=highlight><pre><span></span><code>STRING=&quot;Hello world&quot;
# only print &#39;Hello&#39;
echo &quot;${STRING%??????}&quot;
# only print &#39;world&#39;
echo &quot;${STRING#??????}&quot;
# store it into the same variable
STRING=${STRING#??????}
</code></pre></div> <h2 id=bugs-and-portability-considerations>Bugs and Portability considerations<a class=headerlink href=#bugs-and-portability-considerations title="Permanent link">&para;</a></h2> <ul> <li> <p><strong>Fixed in 4.2.36</strong> (<a href=ftp://ftp.cwru.edu/pub/bash/bash-4.2-patches/bash42-036>patch</a>). Bash doesn't follow either POSIX or its own documentation when expanding either a quoted <code>"$@"</code> or <code>"${arr[@]}"</code> with an adjacent expansion. <code>"$@$x"</code> expands in the same way as <code>"$*$x"</code> - i.e. all parameters plus the adjacent expansion are concatenated into a single argument. As a workaround, each expansion needs to be quoted separately. Unfortunately, this bug took a very long time to notice.<code>~ $ set -- a b c; x=foo; printf '&lt;%s&gt; ' "$@$x" "$*""$x" "$@""$x" &lt;a b cfoo&gt; &lt;a b cfoo&gt; &lt;a&gt; &lt;b&gt; &lt;cfoo&gt;</code></p> </li> <li> <p>Almost all shells disagree about the treatment of an unquoted <code>$@</code>, <code>${arr[@]}</code>, <code>$*</code>, and <code>${arr[*]}</code> when <a href=http://mywiki.wooledge.org/IFS>IFS</a> is set to null. POSIX is unclear about the expected behavior. A null IFS causes both <a href=../expansion/wordsplit/ >word splitting</a> and <a href=../expansion/globs/ >pathname expansion</a> to behave randomly. Since there are few good reasons to leave <code>IFS</code> set to null for more than the duration of a command or two, and even fewer to expand <code>$@</code> and <code>$*</code> unquoted, this should be a rare issue. <strong>Always quote them</strong>!<code>touch x 'y z' for sh in bb {{d,b}a,{m,}k,z}sh; do echo "$sh" "$sh" -s a 'b c' d \* &lt;/dev/fd/0 done &lt;&lt;\EOF ${ZSH_VERSION+:} false &amp;&amp; emulate sh IFS= printf '&lt;%s&gt; ' $* echo printf "&lt;%s&gt; " $@ echo EOF ``bb &lt;ab cd*&gt; &lt;ab cd*&gt; dash &lt;ab cd*&gt; &lt;ab cd*&gt; bash &lt;a&gt; &lt;b c&gt; &lt;d&gt; &lt;x&gt; &lt;y z&gt; &lt;a&gt; &lt;b c&gt; &lt;d&gt; &lt;x&gt; &lt;y z&gt; mksh &lt;a b c d *&gt; &lt;a b c d *&gt; ksh &lt;a&gt; &lt;b c&gt; &lt;d&gt; &lt;x&gt; &lt;y z&gt; &lt;a&gt; &lt;b c&gt; &lt;d&gt; &lt;x&gt; &lt;y z&gt; zsh &lt;a&gt; &lt;b c&gt; &lt;d&gt; &lt;x&gt; &lt;y z&gt; &lt;a&gt; &lt;b c&gt; &lt;d&gt; &lt;x&gt; &lt;y z&gt;</code>When <code>IFS</code> is set to a non-null value, or unset, all shells behave the same - first expanding into separate args, then applying pathname expansion and word-splitting to the results, except for zsh, which doesn't do pathname expansion in its default mode.</p> </li> <li> <p>Additionally, shells disagree about various wordsplitting behaviors, the behavior of inserting delimiter characters from IFS in <code>$*</code>, and the way adjacent arguments are concatenated, when IFS is modified in the middle of expansion through side-effects.<code>for sh in bb {{d,b}a,po,{m,}k,z}sh; do printf '%-4s: ' "$sh" "$sh" &lt;/dev/fd/0 done &lt;&lt;\EOF ${ZSH_VERSION+:} false &amp;&amp; emulate sh set -f -- a b c unset -v IFS printf '&lt;%s&gt; ' ${*}${IFS=}${*}${IFS:=-}"${*}" echo EOF ``bb : &lt;a b cabc&gt; &lt;a-b-c&gt; dash: &lt;a b cabc&gt; &lt;a-b-c&gt; bash: &lt;a&gt; &lt;b&gt; &lt;ca&gt; &lt;b&gt; &lt;c-a b c&gt; posh: &lt;a&gt; &lt;b&gt; &lt;ca b c&gt; &lt;a-b-c&gt; mksh: &lt;a&gt; &lt;b&gt; &lt;ca b c&gt; &lt;a-b-c&gt; ksh : &lt;a&gt; &lt;b&gt; &lt;ca&gt; &lt;b&gt; &lt;c&gt; &lt;a b c&gt; zsh : &lt;a&gt; &lt;b&gt; &lt;ca&gt; &lt;b&gt; &lt;c&gt; &lt;a-b-c&gt;</code>ksh93 and mksh can additionally achieve this side effect (and others) via the <code>${ cmds;}</code> expansion. I haven't yet tested every possible side-effect that can affect expansion halfway through expansion that way.</p> </li> <li> <p>As previously mentioned, the Bash form of indirection by prefixing a parameter expansion with a <code>!</code> conflicts with the same syntax used by mksh, zsh, and ksh93 for a different purpose. Bash will "slightly" modify this expansion in the next version with the addition of namerefs.</p> </li> <li> <p>Bash (and most other shells) don't allow .'s in identifiers. In ksh93, dots in variable names are used to reference methods (i.e. "Discipline Functions"), attributes, special shell variables, and to define the "real value" of an instance of a class.</p> </li> <li> <p>In ksh93, the <code>_</code> parameter has even more uses. It is used in the same way as <code>self</code> in some object-oriented languages; as a placeholder for some data local to a class; and also as the mechanism for class inheritance. In most other contexts, <code>_</code> is compatible with Bash.</p> </li> <li> <p>Bash only evaluates the subscripts of the slice expansion (<code>${x:y:z}</code>) if the parameter is set (for both nested expansions and arithmetic). For ranges, Bash evaluates as little as possible, i.e., if the first part is out of range, the second won't be evaluated. ksh93 and mksh always evaluate the subscript parts even if the parameter is unset. <code>$ bash -c 'n="y[\$(printf yo &gt;&amp;2)1]" m="y[\$(printf jo &gt;&amp;2)1]"; x=(); echo "${x[@]:n,6:m}"' # No output $ bash -c 'n="y[\$(printf yo &gt;&amp;2)1]" m="y[\$(printf jo &gt;&amp;2)1]"; x=([5]=hi); echo "${x[@]:n,6:m}"' yo $ bash -c 'n="y[\$(printf yo &gt;&amp;2)1]" m="y[\$(printf jo &gt;&amp;2)1]"; x=([6]=hi); echo "${x[@]:n,6:m}"' yojo $ bash -c 'n="y[\$(printf yo &gt;&amp;2)1]" m="y[\$(printf jo &gt;&amp;2)1]"; x=12345; echo "${x:n,5:m}"' yojo $ bash -c 'n="y[\$(printf yo &gt;&amp;2)1]" m="y[\$(printf jo &gt;&amp;2)1]"; x=12345; echo "${x:n,6:m}"' yo</code></p> </li> </ul> <h3 id=quote-nesting>Quote Nesting<a class=headerlink href=#quote-nesting title="Permanent link">&para;</a></h3> <ul> <li> <p>In most shells, when dealing with an "alternate" parameter expansion that expands to multiple words, and nesting such expansions, not all combinations of nested quoting are possible.</p> <h1 id=bash>Bash<a class=headerlink href=#bash title="Permanent link">&para;</a></h1> <p>$ typeset -a a=(meh bleh blerg) b $ IFS=e $ printf "&lt;%s&gt; " "${b[@]-"${a[@]}" "${a[@]}"}"; echo # The entire PE is quoted so Bash considers the inner quotes redundant. <meh> <bleh> <blerg meh> <bleh> <blerg> $ printf "&lt;%s&gt; " "${b[@]-${a[@]} ${a[@]}}"; echo # The outer quotes cause the inner expansions to be considered quoted. <meh> <bleh> <blerg meh> <bleh> <blerg> $ b=(meep beep) $ printf "&lt;%s&gt; " "${b[@]-"${a[@]}" "${a[@]}"}" "${b[@]-${a[@]} ${a[@]}}"; echo # Again no surprises. Outer quotes quote everything recursively. <meep> <beep> <meep> <beep></p> </li> </ul> <p>Now lets see what can happen if we leave the outside unquoted.</p> <div class=highlight><pre><span></span><code># Bash
$ typeset -a a=(meh bleh blerg) b
$ IFS=e
$ printf &quot;&lt;%s&gt; &quot; ${b[@]-&quot;${a[@]}&quot; &quot;${a[@]}&quot;}; echo # Inner quotes make inner expansions quoted.
&lt;meh&gt; &lt;bleh&gt; &lt;blerg meh&gt; &lt;bleh&gt; &lt;blerg&gt;
$ printf &quot;&lt;%s&gt; &quot; ${b[@]-${a[@]} ${a[@]}}; echo&#39; # No quotes at all wordsplits / globs, like you&#39;d expect.
&lt;m&gt; &lt;h&gt; &lt;bl&gt; &lt;h&gt; &lt;bl&gt; &lt;rg m&gt; &lt;h&gt; &lt;bl&gt; &lt;h&gt; &lt;bl&gt; &lt;rg&gt;
</code></pre></div> <p>This all might be intuitive, and is the most common implementation, but this design sucks for a number of reasons. For one, it means Bash makes it absolutely impossible to expand any part of the inner region <em>unquoted</em> while leaving the outer region quoted. Quoting the outer forces quoting of the inner regions recursively (except nested command substitutions of course). Word-splitting is necessary to split words of the inner region, which cannot be done together with outer quoting. Consider the following (only slightly far-fetched) code:</p> <div class=highlight><pre><span></span><code># Bash (non-working example)
unset -v IFS # make sure we have a default IFS
if some crap; then
typeset -a someCmd=(myCmd arg1 &#39;arg2 yay!&#39; &#39;third*arg*&#39; 4)
fi
someOtherCmd=mycommand
typeset -a otherArgs=(arg3 arg4)
# What do you think the programmer expected to happen here?
# What do you think will actually happen...
&quot;${someCmd[@]-&quot;$someOtherCmd&quot; arg2 &quot;${otherArgs[@]}&quot;}&quot; arg5
</code></pre></div> <p>This final line is perhaps not the most obvious, but I've run into cases were this type of logic can be desirable and realistic. We can deduce what was intended:</p> <ul> <li>If <code>someCmd</code> is set, then the resulting expansion should run the command: <code>"myCmd" "arg1" "arg2 yay!" "third*arg*" "4" "arg5"</code></li> <li>Otherwise, if <code>someCmd</code> is not set, expand <code>$someOtherCmd</code> and the inner args, to run a different command: <code>"mycommand" "arg2" "arg3" "arg4" "arg5"</code>.</li> </ul> <p>Unfortunately, it is impossible to get the intended result in Bash (and most other shells) without taking a considerably different approach. The only way to split the literal inner parts is through word-splitting, which requires that the PE be unquoted. But, the only way to expand the outer expansion correctly without word-splitting or globbing is to quote it. Bash will actually expand the command as one of these:</p> <div class=highlight><pre><span></span><code># The quoted PE produces a correct result here...
$ bash -c &#39;typeset -a someCmd=(myCmd arg1 &quot;arg2 yay!&quot; &quot;third*arg*&quot; 4); printf &quot;&lt;%s&gt; &quot; &quot;${someCmd[@]-&quot;$someOtherCmd&quot; arg2 &quot;${otherArgs[@]}&quot;}&quot; arg5; echo&#39;
&lt;myCmd&gt; &lt;arg1&gt; &lt;arg2 yay!&gt; &lt;third*arg*&gt; &lt;4&gt; &lt;arg5&gt;
# ...but in the opposite case the first 3 arguments are glued together. There are no workarounds.
$ bash -c &#39;typeset -a otherArgs=(arg3 arg4); someOtherCmd=mycommand; printf &quot;&lt;%s&gt; &quot; &quot;${someCmd[@]-&quot;$someOtherCmd&quot; arg2 &quot;${otherArgs[@]}&quot;}&quot; arg5; echo&#39;
&lt;mycommand arg2 arg3&gt; &lt;arg4&gt; &lt;arg5&gt;
# UNLESS! we unquote the outer expansion allowing the inner quotes to
# affect the necessary parts while allowing word-splitting to split the literals:
$ bash -c &#39;typeset -a otherArgs=(arg3 arg4); someOtherCmd=mycommand; printf &quot;&lt;%s&gt; &quot; ${someCmd[@]-&quot;$someOtherCmd&quot; arg2 &quot;${otherArgs[@]}&quot;} arg5; echo&#39;
&lt;mycommand&gt; &lt;arg2&gt; &lt;arg3&gt; &lt;arg4&gt; &lt;arg5&gt;
# Success!!!
$ bash -c &#39;typeset -a someCmd=(myCmd arg1 &quot;arg2 yay!&quot; &quot;third*arg*&quot; 4); printf &quot;&lt;%s&gt; &quot; ${someCmd[@]-&quot;$someOtherCmd&quot; arg2 &quot;${otherArgs[@]}&quot;} arg5; echo&#39;
&lt;myCmd&gt; &lt;arg1&gt; &lt;arg2&gt; &lt;yay!&gt; &lt;third*arg*&gt; &lt;4&gt; &lt;arg5&gt;
# ...Ah f^^k. (again, no workaround possible.)
</code></pre></div> <h4 id=the-ksh93-exception>The ksh93 exception<a class=headerlink href=#the-ksh93-exception title="Permanent link">&para;</a></h4> <p>To the best of my knowledge, ksh93 is the only shell that acts differently. Rather than forcing nested expansions into quoting, a quote at the beginning and end of the nested region will cause the quote state to reverse itself within the nested part. I have no idea whether it's an intentional or documented effect, but it does solve the problem and consequently adds a lot of potential power to these expansions.</p> <p>All we need to do is add two extra double-quotes:</p> <div class=highlight><pre><span></span><code># ksh93 passing the two failed tests from above:
$ ksh -c &#39;otherArgs=(arg3 arg4); someOtherCmd=&quot;mycommand&quot;; printf &quot;&lt;%s&gt; &quot; &quot;${someCmd[@]-&quot;&quot;$someOtherCmd&quot; arg2 &quot;${otherArgs[@]}&quot;&quot;}&quot; arg5; echo&#39;
&lt;mycommand&gt; &lt;arg2&gt; &lt;arg3&gt; &lt;arg4&gt; &lt;arg5&gt;
$ ksh -c &#39;typeset -a someCmd=(myCmd arg1 &quot;arg2 yay!&quot; &quot;third*arg*&quot; 4); printf &quot;&lt;%s&gt; &quot; &quot;${someCmd[@]-&quot;&quot;$someOtherCmd&quot; arg2 &quot;${otherArgs[@]}&quot;&quot;}&quot; arg5; echo&#39;
&lt;myCmd&gt; &lt;arg1&gt; &lt;arg2 yay!&gt; &lt;third*arg*&gt; &lt;4&gt; &lt;arg5&gt;
</code></pre></div> <p>This can be used to control the quote state of any part of any expansion to an arbitrary depth. Sadly, it is the only shell that does this and the difference may introduce a possible compatibility problem.</p> <h2 id=see-also>See also<a class=headerlink href=#see-also title="Permanent link">&para;</a></h2> <ul> <li>Internal: <a href=../expansion/intro/ >Introduction to expansion and substitution</a></li> <li>Internal: <a href=../arrays/ >Arrays</a></li> <li>Dictionary, internal: <a href=../../dict/parameter/ >parameter</a></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">October 12, 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">October 12, 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.525ec568.min.js></script> </body> </html>