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

62 lines
50 KiB
HTML
Raw Normal View History

<!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/words/ rel=canonical><link href=../shellvars/ rel=prev><link href=../ccmd/arithmetic_eval/ rel=next><link rel=icon href=../../assets/images/favicon.png><meta name=generator content="mkdocs-1.6.1, mkdocs-material-9.5.44"><title>Words... - The Bash Hackers Wiki</title><link rel=stylesheet href=../../assets/stylesheets/main.0253249f.min.css><link rel=stylesheet href=../../assets/stylesheets/palette.06af60db.min.css><link rel=preconnect href=https://fonts.gstatic.com crossorigin><link rel=stylesheet href="https://fonts.googleapis.com/css?family=Roboto:300,300i,400,400i,700,700i%7CRoboto+Mono:400,400i,700,700i&display=fallback"><style>:root{--md-text-font:"Roboto";--md-code-font:"Roboto Mono"}</style><script>__md_scope=new URL("../..",location),__md_hash=e=>[...e].reduce(((e,_)=>(e<<5)-e+_.charCodeAt(0)),0),__md_get=(e,_=localStorage,t=__md_scope)=>JSON.parse(_.getItem(t.pathname+"."+e)),__md_set=(e,_,t=localStorage,a=__md_scope)=>{try{t.setItem(a.pathname+"."+e,JSON.stringify(_))}catch(e){}}</script></head> <body dir=ltr data-md-color-scheme=default data-md-color-primary=indigo data-md-color-accent=indigo> <input class=md-toggle data-md-toggle=drawer type=checkbox id=__drawer autocomplete=off> <input class=md-toggle data-md-toggle=search type=checkbox id=__search autocomplete=off> <label class=md-overlay for=__drawer></label> <div data-md-component=skip> <a href=#words 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> Words... </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=docum
Hello little world
</code></pre></div> <p>In other words, something you do (and Bash does) everyday. The characters where Bash splits the command line (SPACE, TAB i.e. blanks) are recognized as delimiters. There is no null argument generated when you have 2 or more blanks in the command line. <strong>A sequence of more blank characters is treated as a single blank.</strong> Here's an example:</p> <div class=highlight><pre><span></span><code>$ echo Hello little world
Hello little world
</code></pre></div> <p>Bash splits the command line at the blanks into words, then it calls echo with <strong>each word as an argument</strong>. In this example, echo is called with three arguments: "<code>Hello</code>", "<code>little</code>" and "<code>world</code>"!</p> <p><u>Does that mean we can't echo more than one Space?</u> Of course not! Bash treats blanks as special characters, but there are two ways to tell Bash not to treat them special: <strong>Escaping</strong> and <strong>quoting</strong>.</p> <p>Escaping a character means, to <strong>take away its special meaning</strong>. Bash will use an escaped character as text, even if it's a special one. Escaping is done by preceeding the character with a backslash:</p> <div class=highlight><pre><span></span><code>$ echo Hello\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ little \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ world
Hello little world
</code></pre></div> <p>None of the escaped spaces will be used to perform word splitting. Thus, echo is called with one argument: "<code>Hello little world</code>".</p> <p>Bash has a mechanism to "escape" an entire string: <strong>Quoting</strong>. In the context of command-splitting, which this section is about, it doesn't matter which kind of quoting you use: weak quoting or strong quoting, both cause Bash to not treat spaces as special characters:</p> <div class=highlight><pre><span></span><code>$ echo &quot;Hello little world&quot;
Hello little world
$ echo &#39;Hello little world&#39;
Hello little world
</code></pre></div> <p><u>What is it all about now?</u> Well, for example imagine a program that expects a filename as an argument, like cat. Filenames can have spaces in them:</p> <div class=highlight><pre><span></span><code>$ ls -l
total 4
-rw-r--r-- 1 bonsai bonsai 5 Apr 18 18:16 test file
$ cat test file
cat: test: No such file or directory
cat: file: No such file or directory
$ cat test\ file
m00!
$ cat &quot;test file&quot;
m00!
</code></pre></div> <p>If you enter that on the command line with Tab completion, that will take care of the spaces. But Bash also does another type of splitting.</p> <h2 id=word-splitting>Word splitting<a class=headerlink href=#word-splitting title="Permanent link">&para;</a></h2> <p>For a more technical description, please read the <a href=../expansion/wordsplit/ >article about word splitting</a>!</p> <p>The first kind of splitting is done to parse the command line into separate tokens. This is what was described above, it's a pure <strong>command line parsing</strong>.</p> <p>After the command line has been split into words, Bash will perform expansion, if needed - variables that occur in the command line need to be expanded (substituted by their value), for example. This is where the second type of word splitting comes in - several expansions undergo <strong>word splitting</strong> (but others do not).</p> <p>Imagine you have a filename stored in a variable:</p> <div class=highlight><pre><span></span><code>MYFILE=&quot;test file&quot;
</code></pre></div> <p>When this variable is used, its occurance will be replaced by its content.</p> <div class=highlight><pre><span></span><code>$ cat $MYFILE
cat: test: No such file or directory
cat: file: No such file or directory
</code></pre></div> <p>Though this is another step where spaces make things difficult, <strong>quoting</strong> is used to work around the difficulty. Quotes also affect word splitting:</p> <div class=highlight><pre><span></span><code>$ cat &quot;$MYFILE&quot;
m00!
</code></pre></div> <h2 id=example>Example<a class=headerlink href=#example title="Permanent link">&para;</a></h2> <p>Let's follow an unquoted command through these steps, assuming that the variable is set:</p> <div class=highlight><pre><span></span><code>MYFILE=&quot;THE FILE.TXT&quot;
</code></pre></div> <p>and the first review is:</p> <div class=highlight><pre><span></span><code>echo The file is named $MYFILE
</code></pre></div> <p>The parser will scan for blanks and mark the relevant words ("splitting the command line"):</p> <table> <thead> <tr> <th>Initial command line splitting:</th> <th></th> <th></th> <th></th> <th></th> <th></th> </tr> </thead> <tbody> <tr> <td>Word 1</td> <td>Word 2</td> <td>Word 3</td> <td>Word 4</td> <td>Word 5</td> <td>Word 6</td> </tr> <tr> <td><code>echo</code></td> <td><code>The</code></td> <td><code>file</code></td> <td><code>is</code></td> <td><code>named</code></td> <td><code>$MYFILE</code></td> </tr> </tbody> </table> <p>A <a href=../pe/ >parameter/variable expansion</a> is part of that command line, Bash will perform the substitution, and the <a href=../expansion/wordsplit/ >word splitting</a> on the results:</p> <table> <thead> <tr> <th>Word splitting after substitution:</th> <th></th> <th></th> <th></th> <th></th> <th></th> <th></th> </tr> </thead> <tbody> <tr> <td>Word 1</td> <td>Word 2</td> <td>Word 3</td> <td>Word 4</td> <td>Word 5</td> <td>Word 6</td> <td>Word 7</td> </tr> <tr> <td><code>echo</code></td> <td><code>The</code></td> <td><code>file</code></td> <td><code>is</code></td> <td><code>named</code></td> <td><code>THE</code></td> <td><code>FILE.TXT</code></td> </tr> </tbody> </table> <p>Now let's imagine we quoted <code>$MYFILE</code>, the command line now looks like:</p> <div class=highlight><pre><span></span><code>echo The file is named &quot;$MYFILE&quot;
</code></pre></div> <table> <thead> <tr> <th>Word splitting after substitution (quoted!):</th> <th></th> <th></th> <th></th> <th></th> <th></th> </tr> </thead> <tbody> <tr> <td>Word 1</td> <td>Word 2</td> <td>Word 3</td> <td>Word 4</td> <td>Word 5</td> <td>Word 6</td> </tr> <tr> <td><code>echo</code></td> <td><code>The</code></td> <td><code>file</code></td> <td><code>is</code></td> <td><code>named</code></td> <td><code>THE FILE.TXT</code></td> </tr> </tbody> </table> <h1 id=see-also>See also<a class=headerlink href=#see-also title="Permanent link">&para;</a></h1> <ul> <li>Internal: <a href=../quoting/ >Quoting and character escaping</a></li> <li>Internal: <a href=../expansion/wordsplit/ >Word splitting</a></li> <li>Internal: <a href=../expansion/intro/ >Introduction to expansions and substitutions</a></li> <li>External: <a href=http://www.grymoire.com/Unix/Quote.html>Grymore: Shellquoting</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">November 7, 2024</span> </span> <span class=md-source-file__fact> <span class=md-icon title=Created> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 24 24"><path d="M14.47 15.08 11 13V7h1.5v5.25l3.08 1.83c-.41.28-.79.62-1.11 1m-1.39 4.84c-.36.05-.71.08-1.08.08-4.42 0-8-3.58-8-8s3.58-8 8-8 8 3.58 8 8c0 .37-.03.72-.08 1.08.69.1 1.33.32 1.92.64.1-.56.16-1.13.16-1.72 0-5.5-4.5-10-10-10S2 6.5 2 12s4.47 10 10 10c.59 0 1.16-.06 1.72-.16-.32-.59-.54-1.23-.64-1.92M18 15v3h-3v2h3v3h2v-3h3v-2h-3v-3z"/></svg> </span> <span class="git-revision-date-localized-plugin git-revision-date-localized-plugin-date">November 7, 2024</span> </span> </aside> <h2 id=__comments>Comments</h2> <script src=https://giscus.app/client.js data-repo=flokoe/bash-hackers-wiki data-repo-id=R_kgDOJ3Nr6Q data-category="Giscus Page Comments" data-category-id=DIC_kwDOJ3Nr6c4CXq9t data-mapping=pathname data-strict=1 data-reactions-enabled=1 data-emit-metadata=0 data-input-position=top data-theme=preferred_color_scheme data-lang=en data-loading=lazy crossorigin=anonymous async>
</script> <script>
var giscus = document.querySelector("script[src*=giscus]")
/* Set palette on initial load */
var palette = __md_get("__palette")
if (palette && typeof palette.color === "object") {
var theme = palette.color.scheme === "slate" ? "dark" : "light"
giscus.setAttribute("data-theme", theme)
}
/* Register event handlers after documented loaded */
document.addEventListener("DOMContentLoaded", function() {
var ref = document.querySelector("[data-md-component=palette]")
ref.addEventListener("change", function() {
var palette = __md_get("__palette")
if (palette && typeof palette.color === "object") {
var theme = palette.color.scheme === "slate" ? "dark" : "light"
/* Instruct Giscus to change theme */
var frame = document.querySelector(".giscus-frame")
frame.contentWindow.postMessage(
{ giscus: { setConfig: { theme } } },
"https://giscus.app"
)
}
})
})
</script> </article> </div> <script>var target=document.getElementById(location.hash.slice(1));target&&target.name&&(target.checked=target.name.startsWith("__tabbed_"))</script> </div> <button type=button class="md-top md-icon" data-md-component=top hidden> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 24 24"><path d="M13 20h-2V8l-5.5 5.5-1.42-1.42L12 4.16l7.92 7.92-1.42 1.42L13 8z"/></svg> Back to top </button> </main> <footer class=md-footer> <div class="md-footer-meta md-typeset"> <div class="md-footer-meta__inner md-grid"> <div class=md-copyright> Made with <a href=https://squidfunk.github.io/mkdocs-material/ target=_blank rel=noopener> Material for MkDocs </a> </div> </div> </div> </footer> </div> <div class=md-dialog data-md-component=dialog> <div class="md-dialog__inner md-typeset"></div> </div> <script id=__config type=application/json>{"base": "../..", "features": ["navigation.instant", "navigation.tracking", "navigation.tabs", "navigation.sections", "navigation.top", "content.action.view", "content.action.edit", "search.suggest", "search.highlight", "content.code.copy"], "search": "../../assets/javascripts/workers/search.6ce7567c.min.js", "translations": {"clipboard.copied": "Copied to clipboard", "clipboard.copy": "Copy to clipboard", "search.result.more.one": "1 more on this page", "search.result.more.other": "# more on this page", "search.result.none": "No matching documents", "search.result.one": "1 matching document", "search.result.other": "# matching documents", "search.result.placeholder": "Type to start searching", "search.result.term.missing": "Missing", "select.version": "Select version"}}</script> <script src=../../assets/javascripts/bundle.83f73b43.min.js></script> </body> </html>