bash-hackers-wiki/snipplets/print_horizontal_line/index.html

52 lines
55 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/snipplets/print_horizontal_line/ rel=canonical><link href=../prargs/ rel=prev><link href=../rndstr/ rel=next><link rel=icon href=../../assets/images/favicon.png><meta name=generator content="mkdocs-1.6.1, mkdocs-material-9.5.44"><title>Print a horizontal line - 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=#print-a-horizontal-line 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> Print a horizontal line </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=match
</code></pre></div> <h2 id=the-iterative-way>The iterative way<a class=headerlink href=#the-iterative-way title="Permanent link">&para;</a></h2> <p>This one simply loops 20 times, always draws a dash, finally a newline</p> <div class=highlight><pre><span></span><code><a id=__codelineno-1-1 name=__codelineno-1-1 href=#__codelineno-1-1></a><span class=k>for</span><span class=w> </span><span class=o>((</span><span class=nv>x</span><span class=w> </span><span class=o>=</span><span class=w> </span><span class=m>0</span><span class=p>;</span><span class=w> </span>x<span class=w> </span>&lt;<span class=w> </span><span class=m>20</span><span class=p>;</span><span class=w> </span>x++<span class=o>))</span><span class=p>;</span><span class=w> </span><span class=k>do</span>
<a id=__codelineno-1-2 name=__codelineno-1-2 href=#__codelineno-1-2></a><span class=w> </span><span class=nb>printf</span><span class=w> </span>%s<span class=w> </span>-
<a id=__codelineno-1-3 name=__codelineno-1-3 href=#__codelineno-1-3></a><span class=k>done</span>
<a id=__codelineno-1-4 name=__codelineno-1-4 href=#__codelineno-1-4></a><span class=nb>echo</span>
</code></pre></div> <h2 id=the-simple-printf-way>The simple printf way<a class=headerlink href=#the-simple-printf-way title="Permanent link">&para;</a></h2> <p>This one uses the <code>printf</code> command to print an <strong>empty</strong> field with a <strong>minimum field width</strong> of 20 characters. The text is padded with spaces, since there is no text, you get 20 spaces. The spaces are then converted to <code>-</code> by the <code>tr</code> command.</p> <div class=highlight><pre><span></span><code><a id=__codelineno-2-1 name=__codelineno-2-1 href=#__codelineno-2-1></a><span class=nb>printf</span><span class=w> </span><span class=s1>&#39;%20s\n&#39;</span><span class=w> </span><span class=p>|</span><span class=w> </span>tr<span class=w> </span><span class=s1>&#39; &#39;</span><span class=w> </span>-
</code></pre></div> <p>whitout an external command, using the (non-POSIX) substitution expansion and <code>-v</code> option:</p> <div class=highlight><pre><span></span><code><a id=__codelineno-3-1 name=__codelineno-3-1 href=#__codelineno-3-1></a><span class=nb>printf</span><span class=w> </span>-v<span class=w> </span>res<span class=w> </span>%20s
<a id=__codelineno-3-2 name=__codelineno-3-2 href=#__codelineno-3-2></a><span class=nb>printf</span><span class=w> </span><span class=s1>&#39;%s\n&#39;</span><span class=w> </span><span class=s2>&quot;</span><span class=si>${</span><span class=nv>res</span><span class=p>// /-</span><span class=si>}</span><span class=s2>&quot;</span>
</code></pre></div> <h2 id=a-line-across-the-entire-width-of-the-terminal>A line across the entire width of the terminal<a class=headerlink href=#a-line-across-the-entire-width-of-the-terminal title="Permanent link">&para;</a></h2> <p>This is a variant of the above that uses <code>tput cols</code> to find the width of the terminal and set that number as the minimum field witdh.</p> <div class=highlight><pre><span></span><code><a id=__codelineno-4-1 name=__codelineno-4-1 href=#__codelineno-4-1></a><span class=nb>printf</span><span class=w> </span><span class=s1>&#39;%*s\n&#39;</span><span class=w> </span><span class=s2>&quot;</span><span class=si>${</span><span class=nv>COLUMNS</span><span class=k>:-$(</span>tput<span class=w> </span>cols<span class=k>)</span><span class=si>}</span><span class=s2>&quot;</span><span class=w> </span><span class=s1>&#39;&#39;</span><span class=w> </span><span class=p>|</span><span class=w> </span>tr<span class=w> </span><span class=s1>&#39; &#39;</span><span class=w> </span>-
</code></pre></div> <h2 id=the-more-advanced-printf-way>The more advanced printf way<a class=headerlink href=#the-more-advanced-printf-way title="Permanent link">&para;</a></h2> <p>This one is a bit tricky. The format for the <code>printf</code> command is <code>%.0s</code>, which specified a field with the <strong>maximum</strong> length of <strong>zero</strong>. After this field, <code>printf</code> is told to print a dash. You might remember that it's the nature of <code>printf</code> to repeat, if the number of conversion specifications is less than the number of given arguments. With brace expansion <code>{1..20}</code>, 20 arguments are given (you could easily write <code>1 2 3 4 ... 20</code>, of course!). Following happens: The <strong>zero-length field</strong> plus the dash is repeated 20 times. A zero length field is, naturally, invisible. What you see is the dash, repeated 20 times.</p> <div class=highlight><pre><span></span><code><a id=__codelineno-5-1 name=__codelineno-5-1 href=#__codelineno-5-1></a><span class=c1># Note: you might see that as &#39;&#39;%.s&#39;&#39;, which is a (less documented) shorthand for &#39;&#39;%.0s&#39;&#39;</span>
<a id=__codelineno-5-2 name=__codelineno-5-2 href=#__codelineno-5-2></a><span class=nb>printf</span><span class=w> </span><span class=s1>&#39;%.0s-&#39;</span><span class=w> </span><span class=o>{</span><span class=m>1</span>..20<span class=o>}</span><span class=p>;</span><span class=w> </span><span class=nb>echo</span>
</code></pre></div> <p>If the 20 is variable, you can use <a href=../../commands/builtin/eval/ >eval</a> to insert the expansion (take care that using <code>eval</code> is potentially dangerous if you evaluate external data):</p> <div class=highlight><pre><span></span><code><a id=__codelineno-6-1 name=__codelineno-6-1 href=#__codelineno-6-1></a><span class=nb>eval</span><span class=w> </span><span class=nb>printf</span><span class=w> </span>%.0s-<span class=w> </span><span class=s1>&#39;{1..&#39;</span><span class=s2>&quot;</span><span class=si>${</span><span class=nv>COLUMNS</span><span class=k>:-$(</span>tput<span class=w> </span>cols<span class=k>)</span><span class=si>}</span><span class=s2>&quot;</span><span class=se>\}</span><span class=p>;</span><span class=w> </span><span class=nb>echo</span>
</code></pre></div> <p>Or restrict the length to 1 and prefix the arguments with the desired character.</p> <div class=highlight><pre><span></span><code><a id=__codelineno-7-1 name=__codelineno-7-1 href=#__codelineno-7-1></a><span class=nb>eval</span><span class=w> </span><span class=nb>printf</span><span class=w> </span>%.1s<span class=w> </span><span class=s1>&#39;-{1..&#39;</span><span class=s2>&quot;</span><span class=si>${</span><span class=nv>COLUMNS</span><span class=k>:-$(</span>tput<span class=w> </span>cols<span class=k>)</span><span class=si>}</span><span class=s2>&quot;</span><span class=se>\}</span><span class=p>;</span><span class=w> </span><span class=nb>echo</span>
</code></pre></div> <p>You can also do it the crazy ormaaj way™ following basically the same principle as this <a href=../../commands/builtin/eval/#expansion_side-effects>string reverse example</a>. It completely depends on Bash due to its brace expansion evaluation order and array parameter parsing details. As above, the eval only inserts the COLUMNS expansion into the expression and isn't involved in the rest, other than to put the <code>_</code> value into the environment of the <code>_[0]</code> expansion. This works well since we\'re not creating one set of arguments and then editing or deleting them to create another as in the previous examples.</p> <div class=highlight><pre><span></span><code><a id=__codelineno-8-1 name=__codelineno-8-1 href=#__codelineno-8-1></a><span class=nv>_</span><span class=o>=</span>-<span class=w> </span><span class=nb>command</span><span class=w> </span><span class=nb>eval</span><span class=w> </span><span class=nb>printf</span><span class=w> </span>%s<span class=w> </span><span class=s1>&#39;&quot;${_[0]&quot;{0..&#39;</span><span class=s2>&quot;</span><span class=si>${</span><span class=nv>COLUMNS</span><span class=k>:-$(</span>tput<span class=w> </span>cols<span class=k>)</span><span class=si>}</span><span class=s2>&quot;</span><span class=s1>&#39;}&quot;}&quot;&#39;</span><span class=p>;</span><span class=w> </span><span class=nb>echo</span>
</code></pre></div> <h2 id=the-parameter-expansion-way>The parameter expansion way<a class=headerlink href=#the-parameter-expansion-way title="Permanent link">&para;</a></h2> <p>Preparing enough dashes in advance, we can then use a non-POSIX subscript expansion:</p> <div class=highlight><pre><span></span><code><a id=__codelineno-9-1 name=__codelineno-9-1 href=#__codelineno-9-1></a><span class=nv>hr</span><span class=o>=</span>---------------------------------------------------------------<span class=se>\</span>
<a id=__codelineno-9-2 name=__codelineno-9-2 href=#__codelineno-9-2></a>----------------------------------------------------------------
<a id=__codelineno-9-3 name=__codelineno-9-3 href=#__codelineno-9-3></a><span class=nb>printf</span><span class=w> </span><span class=s1>&#39;%s\n&#39;</span><span class=w> </span><span class=s2>&quot;</span><span class=si>${</span><span class=nv>hr</span><span class=p>:</span><span class=nv>0</span><span class=p>:</span><span class=si>${</span><span class=nv>COLUMNS</span><span class=k>:-$(</span>tput<span class=w> </span>cols<span class=k>)</span><span class=si>}}</span><span class=s2>&quot;</span>
</code></pre></div> <p>A more flexible approach, and also using modal terminal line-drawing characters instead of hyphens:</p> <div class=highlight><pre><span></span><code><a id=__codelineno-10-1 name=__codelineno-10-1 href=#__codelineno-10-1></a>hr<span class=o>()</span><span class=w> </span><span class=o>{</span>
<a id=__codelineno-10-2 name=__codelineno-10-2 href=#__codelineno-10-2></a><span class=w> </span><span class=nb>local</span><span class=w> </span><span class=nv>start</span><span class=o>=</span><span class=s1>$&#39;\e(0&#39;</span><span class=w> </span><span class=nv>end</span><span class=o>=</span><span class=s1>$&#39;\e(B&#39;</span><span class=w> </span><span class=nv>line</span><span class=o>=</span><span class=s1>&#39;qqqqqqqqqqqqqqqq&#39;</span>
<a id=__codelineno-10-3 name=__codelineno-10-3 href=#__codelineno-10-3></a><span class=w> </span><span class=nb>local</span><span class=w> </span><span class=nv>cols</span><span class=o>=</span><span class=si>${</span><span class=nv>COLUMNS</span><span class=k>:-$(</span>tput<span class=w> </span>cols<span class=k>)</span><span class=si>}</span>
<a id=__codelineno-10-4 name=__codelineno-10-4 href=#__codelineno-10-4></a><span class=w> </span><span class=k>while</span><span class=w> </span><span class=o>((</span><span class=si>${#</span><span class=nv>line</span><span class=si>}</span><span class=w> </span>&lt;<span class=w> </span>cols<span class=o>))</span><span class=p>;</span><span class=w> </span><span class=k>do</span><span class=w> </span><span class=nv>line</span><span class=o>+=</span><span class=s2>&quot;</span><span class=nv>$line</span><span class=s2>&quot;</span><span class=p>;</span><span class=w> </span><span class=k>done</span>
<a id=__codelineno-10-5 name=__codelineno-10-5 href=#__codelineno-10-5></a><span class=w> </span><span class=nb>printf</span><span class=w> </span><span class=s1>&#39;%s%s%s\n&#39;</span><span class=w> </span><span class=s2>&quot;</span><span class=nv>$start</span><span class=s2>&quot;</span><span class=w> </span><span class=s2>&quot;</span><span class=si>${</span><span class=nv>line</span><span class=p>:</span><span class=nv>0</span><span class=p>:</span><span class=nv>cols</span><span class=si>}</span><span class=s2>&quot;</span><span class=w> </span><span class=s2>&quot;</span><span class=nv>$end</span><span class=s2>&quot;</span>
<a id=__codelineno-10-6 name=__codelineno-10-6 href=#__codelineno-10-6></a><span class=o>}</span>
</code></pre></div> <h2 id=related-articles>Related articles<a class=headerlink href=#related-articles title="Permanent link">&para;</a></h2> <ul> <li><a href=../../commands/builtin/printf/ >printf</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>