<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>CodeonDocs</title><link>https://hiraethecho.github.io/docs/tags/code/</link><description>Recent contentinCodeonDocs</description><generator>Hugo --0.152.2</generator><language>en</language><managingEditor>wyz2016zxc@outlook.com(Hiraeth)</managingEditor><webMaster>wyz2016zxc@outlook.com(Hiraeth)</webMaster><lastBuildDate>Mon, 16 Mar 2026 15:39:39 +0800</lastBuildDate><atom:link href="https://hiraethecho.github.io/docs/tags/code/index.xml" rel="self" type="application/rss+xml"/><item><title>一些sh脚本</title><link>https://hiraethecho.github.io/docs/dev/scripts-example/</link><pubDate>Sat, 25 Oct 2025 00:00:00 +0000</pubDate><author>wyz2016zxc@outlook.com(Hiraeth)</author><guid>https://hiraethecho.github.io/docs/dev/scripts-example/</guid><description>&lt;h1 id="scripts-example"&gt;
&lt;a class="anchor inpage" href="#scripts-example"&gt;#&lt;/a&gt;scripts example&lt;/h1&gt;
&lt;details open&gt;
&lt;summary&gt;TEXT&lt;/summary&gt;&lt;pre
class="codeblock"
&gt;&lt;code class="language-" data-lang=""&gt;find . -name &amp;#34;*.md&amp;#34; -type f -exec grep -lE &amp;#34;Finished&amp;#34; {} &amp;#43; | while read file; do
if ! grep -q &amp;#34;2025-05-31&amp;#34; &amp;#34;$file&amp;#34;; then
number=$(awk &amp;#39;/^pages: [0-9]&amp;#43;/ {print $2}&amp;#39; &amp;#34;$file&amp;#34;)
if [ -n &amp;#34;$number&amp;#34; ]; then
sed -i &amp;#34;/Finished/i\\- 2025-05-31: $number&amp;#34; &amp;#34;$file&amp;#34;
echo &amp;#34;已处理: $file - 插入: - 2025-05-31: $number&amp;#34;
else
echo &amp;#34;跳过: $file (未找到pages数字或有效日期)&amp;#34;
fi
else
echo &amp;#34;排除: $file (包含 2025-05-31)&amp;#34;
fi
done&lt;/code&gt;&lt;button onclick="copyCode(this)" class="copybtn"&gt;copy&lt;/button&gt;&lt;/pre&gt;&lt;/details&gt;
&lt;script&gt;
function copyCode(btn) {
const code = btn.previousElementSibling.textContent.trim();
navigator.clipboard.writeText(code).then(() =&gt; {
btn.innerText = "copied";
setTimeout(() =&gt; (btn.innerText = "copy"), 2000);
});
}
&lt;/script&gt;&lt;details open&gt;
&lt;summary&gt;TEXT&lt;/summary&gt;&lt;pre
class="codeblock"
&gt;&lt;code class="language-" data-lang=""&gt;# 创建备份和日志
backup_dir=&amp;#34;backup_$(date &amp;#43;%Y%m%d)&amp;#34;
mkdir -p &amp;#34;$backup_dir&amp;#34;
log_file=&amp;#34;replace_log.txt&amp;#34;
echo &amp;#34;开始替换操作 $(date)&amp;#34; &amp;gt; &amp;#34;$log_file&amp;#34;
find . -name &amp;#34;*.md&amp;#34; -type f | while read file; do
# 检查文件是否包含目标字符串
if grep -q &amp;#34;- 2025-06-01: Finished&amp;#34; &amp;#34;$file&amp;#34;; then
# 创建备份
cp &amp;#34;$file&amp;#34; &amp;#34;$backup_dir/$(basename &amp;#34;$file&amp;#34;)&amp;#34;
# 执行替换
sed -i &amp;#39;s/- 2025-06-01: Finished/- 2025-05-31: Finished/g&amp;#39; &amp;#34;$file&amp;#34;
# 记录日志
echo &amp;#34;已修改: $file&amp;#34; &amp;gt;&amp;gt; &amp;#34;$log_file&amp;#34;
# 显示变更
echo &amp;#34;=== $file 修改内容 ===&amp;#34;
diff &amp;#34;$backup_dir/$(basename &amp;#34;$file&amp;#34;)&amp;#34; &amp;#34;$file&amp;#34; || true
else
echo &amp;#34;无修改: $file&amp;#34; &amp;gt;&amp;gt; &amp;#34;$log_file&amp;#34;
fi
done
echo &amp;#34;操作完成，备份在 $backup_dir，日志见 $log_file&amp;#34;&lt;/code&gt;&lt;button onclick="copyCode(this)" class="copybtn"&gt;copy&lt;/button&gt;&lt;/pre&gt;&lt;/details&gt;
&lt;script&gt;
function copyCode(btn) {
const code = btn.previousElementSibling.textContent.trim();
navigator.clipboard.writeText(code).then(() =&gt; {
btn.innerText = "copied";
setTimeout(() =&gt; (btn.innerText = "copy"), 2000);
});
}
&lt;/script&gt;&lt;details open&gt;
&lt;summary&gt;TEXT&lt;/summary&gt;&lt;pre
class="codeblock"
&gt;&lt;code class="language-" data-lang=""&gt;find . -name &amp;#34;*.md&amp;#34; -type f -exec grep -l &amp;#34;lists: book&amp;#34; {} &amp;#43; | \
while read file; do
if ! grep -q &amp;#34;Finished&amp;#34; &amp;#34;$file&amp;#34;; then
# 确保文件末尾有空行（避免追加内容粘连）
[ -n &amp;#34;$(tail -c 1 &amp;#34;$file&amp;#34;)&amp;#34; ] &amp;amp;&amp;amp; echo &amp;gt;&amp;gt; &amp;#34;$file&amp;#34;
# 追加内容
echo &amp;#34;- 2025-06-01: Finished&amp;#34; &amp;gt;&amp;gt; &amp;#34;$file&amp;#34;
echo &amp;#34;已处理: $file&amp;#34;
else
echo &amp;#34;跳过: $file (已包含 Finished)&amp;#34;
fi
done&lt;/code&gt;&lt;button onclick="copyCode(this)" class="copybtn"&gt;copy&lt;/button&gt;&lt;/pre&gt;&lt;/details&gt;
&lt;script&gt;
function copyCode(btn) {
const code = btn.previousElementSibling.textContent.trim();
navigator.clipboard.writeText(code).then(() =&gt; {
btn.innerText = "copied";
setTimeout(() =&gt; (btn.innerText = "copy"), 2000);
});
}
&lt;/script&gt;&lt;details open&gt;
&lt;summary&gt;TEXT&lt;/summary&gt;&lt;pre
class="codeblock"
&gt;&lt;code class="language-" data-lang=""&gt;find . -name &amp;#34;*.md&amp;#34; -type f -exec grep -L &amp;#34;Finished&amp;#34; {} &amp;#43; | while read file; do
awk &amp;#39;BEGIN {done=0} /^---/ &amp;amp;&amp;amp; !done {print; print &amp;#34;- 2025-06-01: Finished&amp;#34;; done=1; next} 1&amp;#39; &amp;#34;$file&amp;#34; &amp;gt; tmp &amp;amp;&amp;amp; mv tmp &amp;#34;$file&amp;#34;
done&lt;/code&gt;&lt;button onclick="copyCode(this)" class="copybtn"&gt;copy&lt;/button&gt;&lt;/pre&gt;&lt;/details&gt;
&lt;script&gt;
function copyCode(btn) {
const code = btn.previousElementSibling.textContent.trim();
navigator.clipboard.writeText(code).then(() =&gt; {
btn.innerText = "copied";
setTimeout(() =&gt; (btn.innerText = "copy"), 2000);
});
}
&lt;/script&gt;</description><content:encoded><![CDATA[<h1 id="scripts-example">
  <a class="anchor inpage" href="#scripts-example">#</a>scripts example</h1>
<details open>
    <summary>TEXT</summary><pre
        class="codeblock"
      ><code class="language-" data-lang="">find . -name &#34;*.md&#34; -type f -exec grep -lE &#34;Finished&#34; {} &#43; | while read file; do
  if ! grep -q &#34;2025-05-31&#34; &#34;$file&#34;; then
    number=$(awk &#39;/^pages: [0-9]&#43;/ {print $2}&#39; &#34;$file&#34;)
    if [ -n &#34;$number&#34; ]; then
      sed -i &#34;/Finished/i\\- 2025-05-31: $number&#34; &#34;$file&#34;
      echo &#34;已处理: $file - 插入: - 2025-05-31: $number&#34;
    else
      echo &#34;跳过: $file (未找到pages数字或有效日期)&#34;
    fi
  else
    echo &#34;排除: $file (包含 2025-05-31)&#34;
  fi
done</code><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><details open>
    <summary>TEXT</summary><pre
        class="codeblock"
      ><code class="language-" data-lang=""># 创建备份和日志
backup_dir=&#34;backup_$(date &#43;%Y%m%d)&#34;
mkdir -p &#34;$backup_dir&#34;
log_file=&#34;replace_log.txt&#34;

echo &#34;开始替换操作 $(date)&#34; &gt; &#34;$log_file&#34;

find . -name &#34;*.md&#34; -type f | while read file; do
    # 检查文件是否包含目标字符串
    if grep -q &#34;- 2025-06-01: Finished&#34; &#34;$file&#34;; then
        # 创建备份
        cp &#34;$file&#34; &#34;$backup_dir/$(basename &#34;$file&#34;)&#34;
        # 执行替换
        sed -i &#39;s/- 2025-06-01: Finished/- 2025-05-31: Finished/g&#39; &#34;$file&#34;
        # 记录日志
        echo &#34;已修改: $file&#34; &gt;&gt; &#34;$log_file&#34;
        # 显示变更
        echo &#34;=== $file 修改内容 ===&#34;
        diff &#34;$backup_dir/$(basename &#34;$file&#34;)&#34; &#34;$file&#34; || true
    else
        echo &#34;无修改: $file&#34; &gt;&gt; &#34;$log_file&#34;
    fi
done

echo &#34;操作完成，备份在 $backup_dir，日志见 $log_file&#34;</code><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><details open>
    <summary>TEXT</summary><pre
        class="codeblock"
      ><code class="language-" data-lang="">find . -name &#34;*.md&#34; -type f -exec grep -l &#34;lists: book&#34; {} &#43; | \
while read file; do
    if ! grep -q &#34;Finished&#34; &#34;$file&#34;; then
        # 确保文件末尾有空行（避免追加内容粘连）
        [ -n &#34;$(tail -c 1 &#34;$file&#34;)&#34; ] &amp;&amp; echo &gt;&gt; &#34;$file&#34;
        # 追加内容
        echo &#34;- 2025-06-01: Finished&#34; &gt;&gt; &#34;$file&#34;
        echo &#34;已处理: $file&#34;
    else
        echo &#34;跳过: $file (已包含 Finished)&#34;
    fi
done</code><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><details open>
    <summary>TEXT</summary><pre
        class="codeblock"
      ><code class="language-" data-lang="">find . -name &#34;*.md&#34; -type f -exec grep -L &#34;Finished&#34; {} &#43; | while read file; do
    awk &#39;BEGIN {done=0} /^---/ &amp;&amp; !done {print; print &#34;- 2025-06-01: Finished&#34;; done=1; next} 1&#39; &#34;$file&#34; &gt; tmp &amp;&amp; mv tmp &#34;$file&#34;
done</code><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script>]]></content:encoded></item><item><title>编程语言概览</title><link>https://hiraethecho.github.io/docs/dev/code-lang/</link><pubDate>Sat, 12 Jul 2025 00:00:00 +0000</pubDate><author>wyz2016zxc@outlook.com(Hiraeth)</author><guid>https://hiraethecho.github.io/docs/dev/code-lang/</guid><description>编程语言的类型。主要为AI生成。</description><content:encoded><![CDATA[<h2 id="语言分类">
  <a class="anchor inpage" href="#%e8%af%ad%e8%a8%80%e5%88%86%e7%b1%bb">##</a>语言分类</h2>
<ol>
<li>静态类型 vs. 动态类型
<ul>
<li>静态：类型固定，编译检查（C++/Java）。</li>
<li>动态：类型可变，灵活但易出错（Python/JS）。</li>
</ul>
</li>
<li>编译型 vs. 解释型
<ul>
<li>编译型：直接运行机器码（C++/Go）。</li>
<li>解释型：逐行执行（Python/JS）。</li>
<li>JIT：混合优化（Java/JS V8）。</li>
</ul>
</li>
<li>脚本语言
<ul>
<li>解释型，用于自动化、Web（Python/JS/PHP）。</li>
</ul>
</li>
</ol>
<h3 id="静态类型-vs-动态类型">
  <a class="anchor inpage" href="#%e9%9d%99%e6%80%81%e7%b1%bb%e5%9e%8b-vs-%e5%8a%a8%e6%80%81%e7%b1%bb%e5%9e%8b">###</a>静态类型 vs. 动态类型</h3>
<p>静态类型（Statically Typed）</p>
<ul>
<li>定义：变量、函数参数、返回值等的数据类型在编译时就确定，不能随意更改。</li>
<li>特点：
<ul>
<li>编译时会检查类型错误，避免运行时崩溃。</li>
<li>性能更高（编译器可以优化）。</li>
<li>代码更严谨，适合大型项目。</li>
</ul>
</li>
<li>例子：
<ul>
<li>C/C++/Java/C#/Go/Rust</li>
</ul>
<details open>
    <summary>java</summary><pre
        class="chroma codeblock"
      ><code class="language-java" data-lang="java"
          ><span style="display:flex;"><span><span style="color:#66d9ef">int</span> num <span style="color:#f92672">=</span> 10;  <span style="color:#75715e">// num 只能是整数，不能赋值为字符串</span>
</span></span><span style="display:flex;"><span>num <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;hello&#34;</span>; <span style="color:#f92672">//</span> 编译报错<span style="color:#960050;background-color:#1e0010">！</span></span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script></li>
</ul>
<p>动态类型（Dynamically Typed）</p>
<ul>
<li>定义：变量类型在运行时才确定，可以随时改变。</li>
<li>特点：
<ul>
<li>更灵活，适合快速开发。</li>
<li>运行时可能因类型错误崩溃（如 <code>&quot;1&quot; + 2</code> 可能出错）。</li>
<li>性能稍低（需要运行时检查）。</li>
</ul>
</li>
<li>例子：
<ul>
<li>Python/JavaScript/Ruby/PHP/Lua</li>
</ul>
<details open>
    <summary>python</summary><pre
        class="chroma codeblock"
      ><code class="language-python" data-lang="python"
          ><span style="display:flex;"><span>num <span style="color:#f92672">=</span> <span style="color:#ae81ff">10</span>      <span style="color:#75715e"># num 是整数</span>
</span></span><span style="display:flex;"><span>num <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;hello&#34;</span> <span style="color:#75715e"># 现在 num 变成字符串，不会报错</span></span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script></li>
</ul>
<p>对比总结</p>
<table>
  <thead>
      <tr>
          <th>特性</th>
          <th>静态类型</th>
          <th>动态类型</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>类型检查</td>
          <td>编译时检查</td>
          <td>运行时检查</td>
      </tr>
      <tr>
          <td>性能</td>
          <td>更高（编译器优化）</td>
          <td>稍低（运行时解析）</td>
      </tr>
      <tr>
          <td>灵活性</td>
          <td>低（类型固定）</td>
          <td>高（随时改变类型）</td>
      </tr>
      <tr>
          <td>代表语言</td>
          <td>C/C++/Java/Go/Rust</td>
          <td>Python/JS/Ruby/PHP</td>
      </tr>
  </tbody>
</table>
<h3 id="编译型-vs-解释型">
  <a class="anchor inpage" href="#%e7%bc%96%e8%af%91%e5%9e%8b-vs-%e8%a7%a3%e9%87%8a%e5%9e%8b">###</a>编译型 vs. 解释型</h3>
<p>编译型语言（Compiled Languages）</p>
<ul>
<li>定义：代码先被编译器转换成机器码（二进制文件），再直接由CPU执行。</li>
<li>特点：
<ul>
<li>运行速度快（已经是机器码）。</li>
<li>需要针对不同平台（Windows/Linux/macOS）编译。</li>
<li>调试较麻烦（错误在编译时发现）。</li>
</ul>
</li>
<li>例子：
<ul>
<li>C/C++/Go/Rust</li>
</ul>
<details open>
    <summary>TEXT</summary><pre
        class="codeblock"
      ><code class="language-" data-lang="">源代码（.c） → 编译器（gcc） → 可执行文件（.exe） → CPU执行</code><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script></li>
</ul>
<h3 id="解释型语言interpreted-languages">
  <a class="anchor inpage" href="#%e8%a7%a3%e9%87%8a%e5%9e%8b%e8%af%ad%e8%a8%80interpreted-languages">###</a>解释型语言（Interpreted Languages）</h3>
<ul>
<li>定义：代码由解释器逐行翻译并执行，不生成独立可执行文件。</li>
<li>特点：
<ul>
<li>跨平台性好（只要有解释器就能运行）。</li>
<li>运行速度较慢（每次都要解析）。</li>
<li>调试方便（错误直接显示）。</li>
</ul>
</li>
<li>例子：
<ul>
<li>Python/JavaScript/PHP/Ruby</li>
</ul>
<details open>
    <summary>TEXT</summary><pre
        class="codeblock"
      ><code class="language-" data-lang="">源代码（.py） → 解释器（Python） → 直接执行（不生成.exe）</code><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script></li>
</ul>
<p>repl: read-eval-print loop, 解释器交互式模式</p>
<h3 id="混合型jit-编译">
  <a class="anchor inpage" href="#%e6%b7%b7%e5%90%88%e5%9e%8bjit-%e7%bc%96%e8%af%91">###</a>混合型（JIT 编译）</h3>
<ul>
<li>定义：结合编译和解释，先解释执行，再动态编译优化（如Java/C#/JS V8引擎）。</li>
<li>例子：
<ul>
<li>Java（编译成字节码，JVM解释执行）</li>
<li>JavaScript（V8引擎先解释，再JIT优化）</li>
</ul>
</li>
</ul>
<h3 id="对比总结">
  <a class="anchor inpage" href="#%e5%af%b9%e6%af%94%e6%80%bb%e7%bb%93">###</a>对比总结</h3>
<table>
  <thead>
      <tr>
          <th>特性</th>
          <th>编译型</th>
          <th>解释型</th>
          <th>JIT（混合型）</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>执行方式</td>
          <td>直接运行机器码</td>
          <td>逐行解释执行</td>
          <td>先解释，后编译优化</td>
      </tr>
      <tr>
          <td>速度</td>
          <td>最快</td>
          <td>较慢</td>
          <td>中等（优化后接近编译型）</td>
      </tr>
      <tr>
          <td>跨平台</td>
          <td>需重新编译</td>
          <td>直接运行（依赖解释器）</td>
          <td>依赖虚拟机（如JVM）</td>
      </tr>
      <tr>
          <td>代表语言</td>
          <td>C/C++/Go/Rust</td>
          <td>Python/JS/PHP</td>
          <td>Java/C#/JavaScript</td>
      </tr>
  </tbody>
</table>
<h3 id="脚本语言scripting-languages">
  <a class="anchor inpage" href="#%e8%84%9a%e6%9c%ac%e8%af%ad%e8%a8%80scripting-languages">###</a>脚本语言（Scripting Languages）</h3>
<ul>
<li>脚本语言是解释型语言的一种，通常用于自动化任务或控制其他程序。</li>
<li>特点：
<ul>
<li>不需要编译，直接运行。</li>
<li>语法简单，适合快速开发。</li>
<li>通常嵌入到其他系统中（如JS在浏览器，Lua在游戏引擎）。</li>
</ul>
</li>
</ul>
<p>常见脚本语言</p>
<table>
  <thead>
      <tr>
          <th>语言</th>
          <th>主要用途</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>JavaScript</td>
          <td>网页交互（浏览器）、后端（Node.js）</td>
      </tr>
      <tr>
          <td>Python</td>
          <td>数据分析、自动化脚本、Web后端</td>
      </tr>
      <tr>
          <td>PHP</td>
          <td>传统Web开发（WordPress）</td>
      </tr>
      <tr>
          <td>Lua</td>
          <td>游戏脚本（魔兽世界）、嵌入式扩展</td>
      </tr>
      <tr>
          <td>Ruby</td>
          <td>Web开发（Ruby on Rails）</td>
      </tr>
  </tbody>
</table>
<p>脚本语言 vs. 系统编程语言</p>
<table>
  <thead>
      <tr>
          <th>特性</th>
          <th>脚本语言（Python/JS）</th>
          <th>系统语言（C++/Rust）</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>执行方式</td>
          <td>解释执行</td>
          <td>编译成机器码</td>
      </tr>
      <tr>
          <td>性能</td>
          <td>较慢</td>
          <td>极快</td>
      </tr>
      <tr>
          <td>用途</td>
          <td>自动化、Web、数据分析</td>
          <td>操作系统、游戏引擎、高频交易</td>
      </tr>
  </tbody>
</table>
]]></content:encoded></item><item><title>lua</title><link>https://hiraethecho.github.io/docs/dev/lua/</link><pubDate>Mon, 07 Jul 2025 00:00:00 +0000</pubDate><author>wyz2016zxc@outlook.com(Hiraeth)</author><guid>https://hiraethecho.github.io/docs/dev/lua/</guid><description>&lt;h1 id="lua"&gt;
&lt;a class="anchor inpage" href="#lua"&gt;#&lt;/a&gt;lua&lt;/h1&gt;
&lt;h2 id="variable"&gt;
&lt;a class="anchor inpage" href="#variable"&gt;##&lt;/a&gt;variable&lt;/h2&gt;
&lt;details open&gt;
&lt;summary&gt;lua&lt;/summary&gt;&lt;pre
class="chroma codeblock"
&gt;&lt;code class="language-lua" data-lang="lua"
&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;num &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;42&lt;/span&gt; &lt;span style="color:#75715e"&gt;-- Numbers can be integer or floating point.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;s &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;walternate&amp;#39;&lt;/span&gt; &lt;span style="color:#75715e"&gt;-- Immutable strings like Python.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;t &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;double-quotes are also fine&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;u &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;[[ Double brackets
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; start and end
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; multi-line strings.]]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;t &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;nil&lt;/span&gt; &lt;span style="color:#75715e"&gt;-- Undefines t; Lua has garbage collection.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code
&gt;&lt;button onclick="copyCode(this)" class="copybtn"&gt;copy&lt;/button&gt;&lt;/pre&gt;&lt;/details&gt;
&lt;script&gt;
function copyCode(btn) {
const code = btn.previousElementSibling.textContent.trim();
navigator.clipboard.writeText(code).then(() =&gt; {
btn.innerText = "copied";
setTimeout(() =&gt; (btn.innerText = "copy"), 2000);
});
}
&lt;/script&gt;&lt;h3 id="string"&gt;
&lt;a class="anchor inpage" href="#string"&gt;###&lt;/a&gt;string&lt;/h3&gt;
&lt;h2 id="control"&gt;
&lt;a class="anchor inpage" href="#control"&gt;##&lt;/a&gt;control&lt;/h2&gt;
&lt;details open&gt;
&lt;summary&gt;lua&lt;/summary&gt;&lt;pre
class="chroma codeblock"
&gt;&lt;code class="language-lua" data-lang="lua"
&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; num &lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;40&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; print(&lt;span style="color:#e6db74"&gt;&amp;#39;over 40&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;elseif&lt;/span&gt; s &lt;span style="color:#f92672"&gt;~=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;walternate&amp;#39;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;then&lt;/span&gt; &lt;span style="color:#75715e"&gt;-- ~= is not equals.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;-- Equality check is == like Python; ok for strs.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; io.write(&lt;span style="color:#e6db74"&gt;&amp;#39;not over 40&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;\n&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#39;&lt;/span&gt;) &lt;span style="color:#75715e"&gt;-- Defaults to stdout.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;else&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;-- Variables are global by default.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; thisIsGlobal &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;5&lt;/span&gt; &lt;span style="color:#75715e"&gt;-- Camel case is common.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;-- How to make a variable local:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;local&lt;/span&gt; line &lt;span style="color:#f92672"&gt;=&lt;/span&gt; io.read() &lt;span style="color:#75715e"&gt;-- Reads next stdin line.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;-- String concatenation uses the .. operator:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; print(&lt;span style="color:#e6db74"&gt;&amp;#39;Winter is coming, &amp;#39;&lt;/span&gt; &lt;span style="color:#f92672"&gt;..&lt;/span&gt; line)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;-- Undefined variables return nil.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;-- This is not an error:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;foo &lt;span style="color:#f92672"&gt;=&lt;/span&gt; anUnknownVariable &lt;span style="color:#75715e"&gt;-- Now foo = nil.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;aBoolValue &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;false&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;-- Only nil and false are falsy; 0 and &amp;#39;&amp;#39; are true!&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; &lt;span style="color:#f92672"&gt;not&lt;/span&gt; aBoolValue &lt;span style="color:#66d9ef"&gt;then&lt;/span&gt; print(&lt;span style="color:#e6db74"&gt;&amp;#39;it was false&amp;#39;&lt;/span&gt;) &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;-- &amp;#39;or&amp;#39; and &amp;#39;and&amp;#39; are short-circuited.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;-- This is similar to the a?b:c operator in C/js:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;ans &lt;span style="color:#f92672"&gt;=&lt;/span&gt; aBoolValue &lt;span style="color:#f92672"&gt;and&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;yes&amp;#39;&lt;/span&gt; &lt;span style="color:#f92672"&gt;or&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;no&amp;#39;&lt;/span&gt; &lt;span style="color:#75715e"&gt;--&amp;gt; &amp;#39;no&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;karlSum &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; i &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;100&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt; &lt;span style="color:#75715e"&gt;-- The range includes both ends.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; karlSum &lt;span style="color:#f92672"&gt;=&lt;/span&gt; karlSum &lt;span style="color:#f92672"&gt;+&lt;/span&gt; i
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;-- Use &amp;#34;100, 1, -1&amp;#34; as the range to count down:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;fredSum &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; j &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;100&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;, &lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt; fredSum &lt;span style="color:#f92672"&gt;=&lt;/span&gt; fredSum &lt;span style="color:#f92672"&gt;+&lt;/span&gt; j &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;-- In general, the range is begin, end[, step].&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;-- Another loop construct:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;repeat&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; print(&lt;span style="color:#e6db74"&gt;&amp;#39;the way of the future&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; num &lt;span style="color:#f92672"&gt;=&lt;/span&gt; num &lt;span style="color:#f92672"&gt;-&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;until&lt;/span&gt; num &lt;span style="color:#f92672"&gt;==&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code
&gt;&lt;button onclick="copyCode(this)" class="copybtn"&gt;copy&lt;/button&gt;&lt;/pre&gt;&lt;/details&gt;
&lt;script&gt;
function copyCode(btn) {
const code = btn.previousElementSibling.textContent.trim();
navigator.clipboard.writeText(code).then(() =&gt; {
btn.innerText = "copied";
setTimeout(() =&gt; (btn.innerText = "copy"), 2000);
});
}
&lt;/script&gt;&lt;details open&gt;
&lt;summary&gt;lua&lt;/summary&gt;&lt;pre
class="chroma codeblock"
&gt;&lt;code class="language-lua" data-lang="lua"
&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; k, v &lt;span style="color:#66d9ef"&gt;in&lt;/span&gt; pairs(t) &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; print(k, v)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;array &lt;span style="color:#f92672"&gt;=&lt;/span&gt; {&lt;span style="color:#e6db74"&gt;&amp;#34;Google&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;Runoob&amp;#34;&lt;/span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; key,value &lt;span style="color:#66d9ef"&gt;in&lt;/span&gt; ipairs(array)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; print(key, value)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code
&gt;&lt;button onclick="copyCode(this)" class="copybtn"&gt;copy&lt;/button&gt;&lt;/pre&gt;&lt;/details&gt;
&lt;script&gt;
function copyCode(btn) {
const code = btn.previousElementSibling.textContent.trim();
navigator.clipboard.writeText(code).then(() =&gt; {
btn.innerText = "copied";
setTimeout(() =&gt; (btn.innerText = "copy"), 2000);
});
}
&lt;/script&gt;&lt;h2 id="function"&gt;
&lt;a class="anchor inpage" href="#function"&gt;##&lt;/a&gt;function&lt;/h2&gt;
&lt;details open&gt;
&lt;summary&gt;lua&lt;/summary&gt;&lt;pre
class="chroma codeblock"
&gt;&lt;code class="language-lua" data-lang="lua"
&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;function&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;fib&lt;/span&gt;(n)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; n &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;then&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; fib(n &lt;span style="color:#f92672"&gt;-&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;) &lt;span style="color:#f92672"&gt;+&lt;/span&gt; fib(n &lt;span style="color:#f92672"&gt;-&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;-- Closures and anonymous functions are ok:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;function&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;adder&lt;/span&gt;(x)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;-- The returned function is created when adder is&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;-- called, and remembers the value of x:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;function&lt;/span&gt; (y) &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; x &lt;span style="color:#f92672"&gt;+&lt;/span&gt; y &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;a1 &lt;span style="color:#f92672"&gt;=&lt;/span&gt; adder(&lt;span style="color:#ae81ff"&gt;9&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;a2 &lt;span style="color:#f92672"&gt;=&lt;/span&gt; adder(&lt;span style="color:#ae81ff"&gt;36&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;print(a1(&lt;span style="color:#ae81ff"&gt;16&lt;/span&gt;)) &lt;span style="color:#75715e"&gt;--&amp;gt; 25&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;print(a2(&lt;span style="color:#ae81ff"&gt;64&lt;/span&gt;)) &lt;span style="color:#75715e"&gt;--&amp;gt; 100&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;-- Returns, func calls, and assignments all work&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;-- with lists that may be mismatched in length.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;-- Unmatched receivers are nil;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;-- unmatched senders are discarded.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;x, y, z &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;3&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;4&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;-- Now x = 1, y = 2, z = 3, and 4 is thrown away.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;function&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;bar&lt;/span&gt;(a, b, c)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; print(a, b, c)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;4&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;8&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;15&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;16&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;23&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;42&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;x, y &lt;span style="color:#f92672"&gt;=&lt;/span&gt; bar(&lt;span style="color:#e6db74"&gt;&amp;#39;zaphod&amp;#39;&lt;/span&gt;) &lt;span style="color:#75715e"&gt;--&amp;gt; prints &amp;#34;zaphod nil nil&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;-- Now x = 4, y = 8, values 15...42 are discarded.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;-- Functions are first-class, may be local/global.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;-- These are the same:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;function&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;f&lt;/span&gt;(x) &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; x &lt;span style="color:#f92672"&gt;*&lt;/span&gt; x &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;f &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;function&lt;/span&gt; (x) &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; x &lt;span style="color:#f92672"&gt;*&lt;/span&gt; x &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;-- And so are these:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;local&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;function&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;g&lt;/span&gt;(x) &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; math.sin(x) &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;local&lt;/span&gt; g; g &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;function&lt;/span&gt; (x) &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; math.sin(x) &lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;-- the &amp;#39;local g&amp;#39; decl makes g-self-references ok.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;-- Calls with one string param don&amp;#39;t need parens:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;print &lt;span style="color:#e6db74"&gt;&amp;#39;hello&amp;#39;&lt;/span&gt; &lt;span style="color:#75715e"&gt;-- Works fine.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code
&gt;&lt;button onclick="copyCode(this)" class="copybtn"&gt;copy&lt;/button&gt;&lt;/pre&gt;&lt;/details&gt;
&lt;script&gt;
function copyCode(btn) {
const code = btn.previousElementSibling.textContent.trim();
navigator.clipboard.writeText(code).then(() =&gt; {
btn.innerText = "copied";
setTimeout(() =&gt; (btn.innerText = "copy"), 2000);
});
}
&lt;/script&gt;&lt;p&gt;多变量参数&lt;/p&gt;</description><content:encoded><![CDATA[<h1 id="lua">
  <a class="anchor inpage" href="#lua">#</a>lua</h1>
<h2 id="variable">
  <a class="anchor inpage" href="#variable">##</a>variable</h2>
<details open>
    <summary>lua</summary><pre
        class="chroma codeblock"
      ><code class="language-lua" data-lang="lua"
          ><span style="display:flex;"><span>num <span style="color:#f92672">=</span> <span style="color:#ae81ff">42</span>  <span style="color:#75715e">-- Numbers can be integer or floating point.</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>s <span style="color:#f92672">=</span> <span style="color:#e6db74">&#39;walternate&#39;</span>  <span style="color:#75715e">-- Immutable strings like Python.</span>
</span></span><span style="display:flex;"><span>t <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;double-quotes are also fine&#34;</span>
</span></span><span style="display:flex;"><span>u <span style="color:#f92672">=</span> <span style="color:#e6db74">[[ Double brackets
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">       start and end
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">       multi-line strings.]]</span>
</span></span><span style="display:flex;"><span>t <span style="color:#f92672">=</span> <span style="color:#66d9ef">nil</span>  <span style="color:#75715e">-- Undefines t; Lua has garbage collection.</span></span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><h3 id="string">
  <a class="anchor inpage" href="#string">###</a>string</h3>
<h2 id="control">
  <a class="anchor inpage" href="#control">##</a>control</h2>
<details open>
    <summary>lua</summary><pre
        class="chroma codeblock"
      ><code class="language-lua" data-lang="lua"
          ><span style="display:flex;"><span><span style="color:#66d9ef">if</span> num <span style="color:#f92672">&gt;</span> <span style="color:#ae81ff">40</span> <span style="color:#66d9ef">then</span>
</span></span><span style="display:flex;"><span>  print(<span style="color:#e6db74">&#39;over 40&#39;</span>)
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">elseif</span> s <span style="color:#f92672">~=</span> <span style="color:#e6db74">&#39;walternate&#39;</span> <span style="color:#66d9ef">then</span>  <span style="color:#75715e">-- ~= is not equals.</span>
</span></span><span style="display:flex;"><span>  <span style="color:#75715e">-- Equality check is == like Python; ok for strs.</span>
</span></span><span style="display:flex;"><span>  io.write(<span style="color:#e6db74">&#39;not over 40</span><span style="color:#ae81ff">\n</span><span style="color:#e6db74">&#39;</span>)  <span style="color:#75715e">-- Defaults to stdout.</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">else</span>
</span></span><span style="display:flex;"><span>  <span style="color:#75715e">-- Variables are global by default.</span>
</span></span><span style="display:flex;"><span>  thisIsGlobal <span style="color:#f92672">=</span> <span style="color:#ae81ff">5</span>  <span style="color:#75715e">-- Camel case is common.</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#75715e">-- How to make a variable local:</span>
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">local</span> line <span style="color:#f92672">=</span> io.read()  <span style="color:#75715e">-- Reads next stdin line.</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#75715e">-- String concatenation uses the .. operator:</span>
</span></span><span style="display:flex;"><span>  print(<span style="color:#e6db74">&#39;Winter is coming, &#39;</span> <span style="color:#f92672">..</span> line)
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">end</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">-- Undefined variables return nil.</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">-- This is not an error:</span>
</span></span><span style="display:flex;"><span>foo <span style="color:#f92672">=</span> anUnknownVariable  <span style="color:#75715e">-- Now foo = nil.</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>aBoolValue <span style="color:#f92672">=</span> <span style="color:#66d9ef">false</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">-- Only nil and false are falsy; 0 and &#39;&#39; are true!</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">if</span> <span style="color:#f92672">not</span> aBoolValue <span style="color:#66d9ef">then</span> print(<span style="color:#e6db74">&#39;it was false&#39;</span>) <span style="color:#66d9ef">end</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">-- &#39;or&#39; and &#39;and&#39; are short-circuited.</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">-- This is similar to the a?b:c operator in C/js:</span>
</span></span><span style="display:flex;"><span>ans <span style="color:#f92672">=</span> aBoolValue <span style="color:#f92672">and</span> <span style="color:#e6db74">&#39;yes&#39;</span> <span style="color:#f92672">or</span> <span style="color:#e6db74">&#39;no&#39;</span>  <span style="color:#75715e">--&gt; &#39;no&#39;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>karlSum <span style="color:#f92672">=</span> <span style="color:#ae81ff">0</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">for</span> i <span style="color:#f92672">=</span> <span style="color:#ae81ff">1</span>, <span style="color:#ae81ff">100</span> <span style="color:#66d9ef">do</span>  <span style="color:#75715e">-- The range includes both ends.</span>
</span></span><span style="display:flex;"><span>  karlSum <span style="color:#f92672">=</span> karlSum <span style="color:#f92672">+</span> i
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">end</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">-- Use &#34;100, 1, -1&#34; as the range to count down:</span>
</span></span><span style="display:flex;"><span>fredSum <span style="color:#f92672">=</span> <span style="color:#ae81ff">0</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">for</span> j <span style="color:#f92672">=</span> <span style="color:#ae81ff">100</span>, <span style="color:#ae81ff">1</span>, <span style="color:#f92672">-</span><span style="color:#ae81ff">1</span> <span style="color:#66d9ef">do</span> fredSum <span style="color:#f92672">=</span> fredSum <span style="color:#f92672">+</span> j <span style="color:#66d9ef">end</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">-- In general, the range is begin, end[, step].</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">-- Another loop construct:</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">repeat</span>
</span></span><span style="display:flex;"><span>  print(<span style="color:#e6db74">&#39;the way of the future&#39;</span>)
</span></span><span style="display:flex;"><span>  num <span style="color:#f92672">=</span> num <span style="color:#f92672">-</span> <span style="color:#ae81ff">1</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">until</span> num <span style="color:#f92672">==</span> <span style="color:#ae81ff">0</span></span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><details open>
    <summary>lua</summary><pre
        class="chroma codeblock"
      ><code class="language-lua" data-lang="lua"
          ><span style="display:flex;"><span><span style="color:#66d9ef">for</span> k, v <span style="color:#66d9ef">in</span> pairs(t) <span style="color:#66d9ef">do</span>
</span></span><span style="display:flex;"><span>    print(k, v)
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">end</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>array <span style="color:#f92672">=</span> {<span style="color:#e6db74">&#34;Google&#34;</span>, <span style="color:#e6db74">&#34;Runoob&#34;</span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">for</span> key,value <span style="color:#66d9ef">in</span> ipairs(array)
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">do</span>
</span></span><span style="display:flex;"><span>   print(key, value)
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">end</span></span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><h2 id="function">
  <a class="anchor inpage" href="#function">##</a>function</h2>
<details open>
    <summary>lua</summary><pre
        class="chroma codeblock"
      ><code class="language-lua" data-lang="lua"
          ><span style="display:flex;"><span><span style="color:#66d9ef">function</span> <span style="color:#a6e22e">fib</span>(n)
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">if</span> n <span style="color:#f92672">&lt;</span> <span style="color:#ae81ff">2</span> <span style="color:#66d9ef">then</span> <span style="color:#66d9ef">return</span> <span style="color:#ae81ff">1</span> <span style="color:#66d9ef">end</span>
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">return</span> fib(n <span style="color:#f92672">-</span> <span style="color:#ae81ff">2</span>) <span style="color:#f92672">+</span> fib(n <span style="color:#f92672">-</span> <span style="color:#ae81ff">1</span>)
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">end</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">-- Closures and anonymous functions are ok:</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">function</span> <span style="color:#a6e22e">adder</span>(x)
</span></span><span style="display:flex;"><span>  <span style="color:#75715e">-- The returned function is created when adder is</span>
</span></span><span style="display:flex;"><span>  <span style="color:#75715e">-- called, and remembers the value of x:</span>
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">return</span> <span style="color:#66d9ef">function</span> (y) <span style="color:#66d9ef">return</span> x <span style="color:#f92672">+</span> y <span style="color:#66d9ef">end</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">end</span>
</span></span><span style="display:flex;"><span>a1 <span style="color:#f92672">=</span> adder(<span style="color:#ae81ff">9</span>)
</span></span><span style="display:flex;"><span>a2 <span style="color:#f92672">=</span> adder(<span style="color:#ae81ff">36</span>)
</span></span><span style="display:flex;"><span>print(a1(<span style="color:#ae81ff">16</span>))  <span style="color:#75715e">--&gt; 25</span>
</span></span><span style="display:flex;"><span>print(a2(<span style="color:#ae81ff">64</span>))  <span style="color:#75715e">--&gt; 100</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">-- Returns, func calls, and assignments all work</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">-- with lists that may be mismatched in length.</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">-- Unmatched receivers are nil;</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">-- unmatched senders are discarded.</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>x, y, z <span style="color:#f92672">=</span> <span style="color:#ae81ff">1</span>, <span style="color:#ae81ff">2</span>, <span style="color:#ae81ff">3</span>, <span style="color:#ae81ff">4</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">-- Now x = 1, y = 2, z = 3, and 4 is thrown away.</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">function</span> <span style="color:#a6e22e">bar</span>(a, b, c)
</span></span><span style="display:flex;"><span>  print(a, b, c)
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">return</span> <span style="color:#ae81ff">4</span>, <span style="color:#ae81ff">8</span>, <span style="color:#ae81ff">15</span>, <span style="color:#ae81ff">16</span>, <span style="color:#ae81ff">23</span>, <span style="color:#ae81ff">42</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">end</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>x, y <span style="color:#f92672">=</span> bar(<span style="color:#e6db74">&#39;zaphod&#39;</span>)  <span style="color:#75715e">--&gt; prints &#34;zaphod  nil nil&#34;</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">-- Now x = 4, y = 8, values 15...42 are discarded.</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">-- Functions are first-class, may be local/global.</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">-- These are the same:</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">function</span> <span style="color:#a6e22e">f</span>(x) <span style="color:#66d9ef">return</span> x <span style="color:#f92672">*</span> x <span style="color:#66d9ef">end</span>
</span></span><span style="display:flex;"><span>f <span style="color:#f92672">=</span> <span style="color:#66d9ef">function</span> (x) <span style="color:#66d9ef">return</span> x <span style="color:#f92672">*</span> x <span style="color:#66d9ef">end</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">-- And so are these:</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">local</span> <span style="color:#66d9ef">function</span> <span style="color:#a6e22e">g</span>(x) <span style="color:#66d9ef">return</span> math.sin(x) <span style="color:#66d9ef">end</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">local</span> g; g  <span style="color:#f92672">=</span> <span style="color:#66d9ef">function</span> (x) <span style="color:#66d9ef">return</span> math.sin(x) <span style="color:#66d9ef">end</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">-- the &#39;local g&#39; decl makes g-self-references ok.</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">-- Calls with one string param don&#39;t need parens:</span>
</span></span><span style="display:flex;"><span>print <span style="color:#e6db74">&#39;hello&#39;</span>  <span style="color:#75715e">-- Works fine.</span></span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><p>多变量参数</p>
<details open>
    <summary>lua</summary><pre
        class="chroma codeblock"
      ><code class="language-lua" data-lang="lua"
          ><span style="display:flex;"><span><span style="color:#75715e">--[[
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">local function 函数名(...)
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">    local args = {...} -- 转为表
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">    -- 处理args
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">end
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">]]</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">local</span> <span style="color:#66d9ef">function</span> <span style="color:#a6e22e">sum</span>(...)
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">local</span> result <span style="color:#f92672">=</span> <span style="color:#ae81ff">0</span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">for</span> _, num <span style="color:#66d9ef">in</span> ipairs({...}) <span style="color:#66d9ef">do</span>
</span></span><span style="display:flex;"><span>        result <span style="color:#f92672">=</span> result <span style="color:#f92672">+</span> num
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">end</span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">return</span> result
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">end</span>
</span></span><span style="display:flex;"><span>print(sum(<span style="color:#ae81ff">1</span>, <span style="color:#ae81ff">2</span>, <span style="color:#ae81ff">3</span>)) <span style="color:#75715e">-- 输出: 6</span></span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><p>另一种定义函数的语法</p>
<details open>
    <summary>lua</summary><pre
        class="chroma codeblock"
      ><code class="language-lua" data-lang="lua"
          ><span style="display:flex;"><span><span style="color:#66d9ef">local</span> greet <span style="color:#f92672">=</span> <span style="color:#66d9ef">function</span>(name)
</span></span><span style="display:flex;"><span>    print(<span style="color:#e6db74">&#34;Hello, &#34;</span> <span style="color:#f92672">..</span> name)
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">end</span>
</span></span><span style="display:flex;"><span>greet(<span style="color:#e6db74">&#34;World&#34;</span>) <span style="color:#75715e">-- 输出: Hello, World</span></span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><p>表成员函数风格模拟对象：</p>
<details open>
    <summary>lua</summary><pre
        class="chroma codeblock"
      ><code class="language-lua" data-lang="lua"
          ><span style="display:flex;"><span><span style="color:#66d9ef">local</span> person <span style="color:#f92672">=</span> {
</span></span><span style="display:flex;"><span>    name <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;Alice&#34;</span>,
</span></span><span style="display:flex;"><span>    sayHi <span style="color:#f92672">=</span> <span style="color:#66d9ef">function</span>(self)
</span></span><span style="display:flex;"><span>        print(<span style="color:#e6db74">&#34;Hi, I&#39;m &#34;</span> <span style="color:#f92672">..</span> self.name)
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">end</span>
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>person:sayHi() <span style="color:#75715e">-- 输出: Hi, I&#39;m Alice</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">-- 等价于 person.sayHi(person)</span></span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><h2 id="table">
  <a class="anchor inpage" href="#table">##</a>table</h2>
<h3 id="basic">
  <a class="anchor inpage" href="#basic">###</a>basic</h3>
<details open>
    <summary>lua</summary><pre
        class="chroma codeblock"
      ><code class="language-lua" data-lang="lua"
          ><span style="display:flex;"><span><span style="color:#75715e">-- Dict literals have string keys by default:</span>
</span></span><span style="display:flex;"><span>t <span style="color:#f92672">=</span> {key1 <span style="color:#f92672">=</span> <span style="color:#e6db74">&#39;value1&#39;</span>, key2 <span style="color:#f92672">=</span> <span style="color:#66d9ef">false</span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">-- String keys can use js-like dot notation:</span>
</span></span><span style="display:flex;"><span>print(t.key1)  <span style="color:#75715e">-- Prints &#39;value1&#39;.</span>
</span></span><span style="display:flex;"><span>t.newKey <span style="color:#f92672">=</span> {}  <span style="color:#75715e">-- Adds a new key/value pair.</span>
</span></span><span style="display:flex;"><span>t.key2 <span style="color:#f92672">=</span> <span style="color:#66d9ef">nil</span>   <span style="color:#75715e">-- Removes key2 from the table.</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">-- Literal notation for any (non-nil) value as key:</span>
</span></span><span style="display:flex;"><span>u <span style="color:#f92672">=</span> {[<span style="color:#e6db74">&#39;@!#&#39;</span>] <span style="color:#f92672">=</span> <span style="color:#e6db74">&#39;qbert&#39;</span>, [{}] <span style="color:#f92672">=</span> <span style="color:#ae81ff">1729</span>, [<span style="color:#ae81ff">6.28</span>] <span style="color:#f92672">=</span> <span style="color:#e6db74">&#39;tau&#39;</span>}
</span></span><span style="display:flex;"><span>print(u[<span style="color:#ae81ff">6.28</span>])  <span style="color:#75715e">-- prints &#34;tau&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">-- Key matching is basically by value for numbers</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">-- and strings, but by identity for tables.</span>
</span></span><span style="display:flex;"><span>a <span style="color:#f92672">=</span> u[<span style="color:#e6db74">&#39;@!#&#39;</span>]  <span style="color:#75715e">-- Now a = &#39;qbert&#39;.</span>
</span></span><span style="display:flex;"><span>b <span style="color:#f92672">=</span> u[{}]     <span style="color:#75715e">-- We might expect 1729, but it&#39;s nil:</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">-- b = nil since the lookup fails. It fails</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">-- because the key we used is not the same object</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">-- as the one used to store the original value. So</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">-- strings &amp; numbers are more portable keys.</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">-- A one-table-param function call needs no parens:</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">function</span> <span style="color:#a6e22e">h</span>(x) print(x.key1) <span style="color:#66d9ef">end</span>
</span></span><span style="display:flex;"><span>h{key1 <span style="color:#f92672">=</span> <span style="color:#e6db74">&#39;Sonmi~451&#39;</span>}  <span style="color:#75715e">-- Prints &#39;Sonmi~451&#39;.</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">for</span> key, val <span style="color:#66d9ef">in</span> pairs(u) <span style="color:#66d9ef">do</span>  <span style="color:#75715e">-- Table iteration.</span>
</span></span><span style="display:flex;"><span>  print(key, val)
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">end</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">-- _G is a special table of all globals.</span>
</span></span><span style="display:flex;"><span>print(_G[<span style="color:#e6db74">&#39;_G&#39;</span>] <span style="color:#f92672">==</span> _G)  <span style="color:#75715e">-- Prints &#39;true&#39;.</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">-- Using tables as lists / arrays:</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">-- List literals implicitly set up int keys:</span>
</span></span><span style="display:flex;"><span>v <span style="color:#f92672">=</span> {<span style="color:#e6db74">&#39;value1&#39;</span>, <span style="color:#e6db74">&#39;value2&#39;</span>, <span style="color:#ae81ff">1.21</span>, <span style="color:#e6db74">&#39;gigawatts&#39;</span>}
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">for</span> i <span style="color:#f92672">=</span> <span style="color:#ae81ff">1</span>, <span style="color:#f92672">#</span>v <span style="color:#66d9ef">do</span>  <span style="color:#75715e">-- #v is the size of v for lists.</span>
</span></span><span style="display:flex;"><span>  print(v[i])  <span style="color:#75715e">-- Indices start at 1 !! SO CRAZY!</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">end</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">-- A &#39;list&#39; is not a real type. v is just a table</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">-- with consecutive integer keys, treated as a list.</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">-- 初始化表</span>
</span></span><span style="display:flex;"><span>mytable <span style="color:#f92672">=</span> {}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">-- 指定值</span>
</span></span><span style="display:flex;"><span>mytable[<span style="color:#ae81ff">1</span>]<span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;Lua&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">-- 移除引用</span>
</span></span><span style="display:flex;"><span>mytable <span style="color:#f92672">=</span> <span style="color:#66d9ef">nil</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">-- lua 垃圾回收会释放内存</span></span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><details open>
    <summary>lua</summary><pre
        class="chroma codeblock"
      ><code class="language-lua" data-lang="lua"
          ><span style="display:flex;"><span><span style="color:#75715e">-- 简单的 table</span>
</span></span><span style="display:flex;"><span>mytable <span style="color:#f92672">=</span> {}
</span></span><span style="display:flex;"><span>print(<span style="color:#e6db74">&#34;mytable 的类型是 &#34;</span>,type(mytable))
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>mytable[<span style="color:#ae81ff">1</span>]<span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;Lua&#34;</span>
</span></span><span style="display:flex;"><span>mytable[<span style="color:#e6db74">&#34;wow&#34;</span>] <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;修改前&#34;</span>
</span></span><span style="display:flex;"><span>print(<span style="color:#e6db74">&#34;mytable 索引为 1 的元素是 &#34;</span>, mytable[<span style="color:#ae81ff">1</span>])
</span></span><span style="display:flex;"><span>print(<span style="color:#e6db74">&#34;mytable 索引为 wow 的元素是 &#34;</span>, mytable[<span style="color:#e6db74">&#34;wow&#34;</span>])
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">-- alternatetable和mytable的是指同一个 table</span>
</span></span><span style="display:flex;"><span>alternatetable <span style="color:#f92672">=</span> mytable
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>print(<span style="color:#e6db74">&#34;alternatetable 索引为 1 的元素是 &#34;</span>, alternatetable[<span style="color:#ae81ff">1</span>])
</span></span><span style="display:flex;"><span>print(<span style="color:#e6db74">&#34;alternatetable 索引为 wow 的元素是 &#34;</span>, alternatetable[<span style="color:#e6db74">&#34;wow&#34;</span>])
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>alternatetable[<span style="color:#e6db74">&#34;wow&#34;</span>] <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;修改后&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>print(<span style="color:#e6db74">&#34;mytable 索引为 wow 的元素是 &#34;</span>, mytable[<span style="color:#e6db74">&#34;wow&#34;</span>])
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">-- 释放变量</span>
</span></span><span style="display:flex;"><span>alternatetable <span style="color:#f92672">=</span> <span style="color:#66d9ef">nil</span>
</span></span><span style="display:flex;"><span>print(<span style="color:#e6db74">&#34;alternatetable 是 &#34;</span>, alternatetable)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">-- mytable 仍然可以访问</span>
</span></span><span style="display:flex;"><span>print(<span style="color:#e6db74">&#34;mytable 索引为 wow 的元素是 &#34;</span>, mytable[<span style="color:#e6db74">&#34;wow&#34;</span>])
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>mytable <span style="color:#f92672">=</span> <span style="color:#66d9ef">nil</span>
</span></span><span style="display:flex;"><span>print(<span style="color:#e6db74">&#34;mytable 是 &#34;</span>, mytable)</span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><p>输出</p>
<details open>
    <summary>TEXT</summary><pre
        class="codeblock"
      ><code class="language-" data-lang="">mytable 的类型是        table
mytable 索引为 1 的元素是       Lua
mytable 索引为 wow 的元素是     修改前
alternatetable 索引为 1 的元素是        Lua
alternatetable 索引为 wow 的元素是      修改前
mytable 索引为 wow 的元素是     修改后
alternatetable 是       nil
mytable 索引为 wow 的元素是     修改后
mytable 是      nil</code><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><p>当键名是合法标识符时，<code>tbl.text</code> 是 <code>tbl[&quot;text&quot;]</code> 的语法糖。</p>
<h3 id="class-like">
  <a class="anchor inpage" href="#class-like">###</a>class-like</h3>
<details open>
    <summary>lua</summary><pre
        class="chroma codeblock"
      ><code class="language-lua" data-lang="lua"
          ><span style="display:flex;"><span><span style="color:#75715e">-- Explanation for this example is below it.</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>Dog <span style="color:#f92672">=</span> {}                                   <span style="color:#75715e">-- 1.</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">function</span> <span style="color:#a6e22e">Dog</span>:<span style="color:#a6e22e">new</span>()                         <span style="color:#75715e">-- 2.</span>
</span></span><span style="display:flex;"><span>  newObj <span style="color:#f92672">=</span> {sound <span style="color:#f92672">=</span> <span style="color:#e6db74">&#39;woof&#39;</span>}                <span style="color:#75715e">-- 3.</span>
</span></span><span style="display:flex;"><span>  self.__index <span style="color:#f92672">=</span> self                      <span style="color:#75715e">-- 4.</span>
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">return</span> setmetatable(newObj, self)        <span style="color:#75715e">-- 5.</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">end</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">function</span> <span style="color:#a6e22e">Dog</span>:<span style="color:#a6e22e">makeSound</span>()                   <span style="color:#75715e">-- 6.</span>
</span></span><span style="display:flex;"><span>  print(<span style="color:#e6db74">&#39;I say &#39;</span> <span style="color:#f92672">..</span> self.sound)
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">end</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>mrDog <span style="color:#f92672">=</span> Dog:new()                          <span style="color:#75715e">-- 7.</span>
</span></span><span style="display:flex;"><span>mrDog:makeSound()  <span style="color:#75715e">-- &#39;I say woof&#39;         -- 8.</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">-- 1. Dog acts like a class; it&#39;s really a table.</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">-- 2. function tablename:fn(...) is the same as</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">--    function tablename.fn(self, ...)</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">--    The : just adds a first arg called self.</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">--    Read 7 &amp; 8 below for how self gets its value.</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">-- 3. newObj will be an instance of class Dog.</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">-- 4. self = the class being instantiated. Often</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">--    self = Dog, but inheritance can change it.</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">--    newObj gets self&#39;s functions when we set both</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">--    newObj&#39;s metatable and self&#39;s __index to self.</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">-- 5. Reminder: setmetatable returns its first arg.</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">-- 6. The : works as in 2, but this time we expect</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">--    self to be an instance instead of a class.</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">-- 7. Same as Dog.new(Dog), so self = Dog in new().</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">-- 8. Same as mrDog.makeSound(mrDog); self = mrDog.</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">----------------------------------------------------</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">-- Inheritance example:</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>LoudDog <span style="color:#f92672">=</span> Dog:new()                           <span style="color:#75715e">-- 1.</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">function</span> <span style="color:#a6e22e">LoudDog</span>:<span style="color:#a6e22e">makeSound</span>()
</span></span><span style="display:flex;"><span>  s <span style="color:#f92672">=</span> self.sound <span style="color:#f92672">..</span> <span style="color:#e6db74">&#39; &#39;</span>                       <span style="color:#75715e">-- 2.</span>
</span></span><span style="display:flex;"><span>  print(s <span style="color:#f92672">..</span> s <span style="color:#f92672">..</span> s)
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">end</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>seymour <span style="color:#f92672">=</span> LoudDog:new()                       <span style="color:#75715e">-- 3.</span>
</span></span><span style="display:flex;"><span>seymour:makeSound()  <span style="color:#75715e">-- &#39;woof woof woof&#39;      -- 4.</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">-- 1. LoudDog gets Dog&#39;s methods and variables.</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">-- 2. self has a &#39;sound&#39; key from new(), see 3.</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">-- 3. Same as LoudDog.new(LoudDog), and converted to</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">--    Dog.new(LoudDog) as LoudDog has no &#39;new&#39; key,</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">--    but does have __index = Dog on its metatable.</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">--    Result: seymour&#39;s metatable is LoudDog, and</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">--    LoudDog.__index = LoudDog. So seymour.key will</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">--    = seymour.key, LoudDog.key, Dog.key, whichever</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">--    table is the first with the given key.</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">-- 4. The &#39;makeSound&#39; key is found in LoudDog; this</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">--    is the same as LoudDog.makeSound(seymour).</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">-- If needed, a subclass&#39;s new() is like the base&#39;s:</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">function</span> <span style="color:#a6e22e">LoudDog</span>:<span style="color:#a6e22e">new</span>()
</span></span><span style="display:flex;"><span>  newObj <span style="color:#f92672">=</span> {}
</span></span><span style="display:flex;"><span>  <span style="color:#75715e">-- set up newObj</span>
</span></span><span style="display:flex;"><span>  self.__index <span style="color:#f92672">=</span> self
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">return</span> setmetatable(newObj, self)
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">end</span></span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><h2 id="module">
  <a class="anchor inpage" href="#module">##</a>module</h2>
<details open>
    <summary>lua</summary><pre
        class="chroma codeblock"
      ><code class="language-lua" data-lang="lua"
          ><span style="display:flex;"><span><span style="color:#66d9ef">local</span> M <span style="color:#f92672">=</span> {}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">local</span> <span style="color:#66d9ef">function</span> <span style="color:#a6e22e">sayMyName</span>()
</span></span><span style="display:flex;"><span>  print(<span style="color:#e6db74">&#39;Hrunkner&#39;</span>)
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">end</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">function</span> <span style="color:#a6e22e">M</span>.<span style="color:#a6e22e">sayHello</span>()
</span></span><span style="display:flex;"><span>  print(<span style="color:#e6db74">&#39;Why hello there&#39;</span>)
</span></span><span style="display:flex;"><span>  sayMyName()
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">end</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">return</span> M
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">-- Another file can use mod.lua&#39;s functionality:</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">local</span> mod <span style="color:#f92672">=</span> require(<span style="color:#e6db74">&#39;mod&#39;</span>)  <span style="color:#75715e">-- Run the file mod.lua.</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">-- require is the standard way to include modules.</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">-- require acts like:     (if not cached; see below)</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">local</span> mod <span style="color:#f92672">=</span> (<span style="color:#66d9ef">function</span> ()
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&lt;</span>contents of mod.lua<span style="color:#f92672">&gt;</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">end</span>)()
</span></span><span style="display:flex;"><span><span style="color:#75715e">-- It&#39;s like mod.lua is a function body, so that</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">-- locals inside mod.lua are invisible outside it.</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">-- This works because mod here = M in mod.lua:</span>
</span></span><span style="display:flex;"><span>mod.sayHello() <span style="color:#75715e">-- Prints: Why hello there Hrunkner</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">-- This is wrong; sayMyName only exists in mod.lua:</span>
</span></span><span style="display:flex;"><span>mod.sayMyName()  <span style="color:#75715e">-- error</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">-- require&#39;s return values are cached so a file is</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">-- run at most once, even when require&#39;d many times.</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">-- Suppose mod2.lua contains &#34;print(&#39;Hi!&#39;)&#34;.</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">local</span> a <span style="color:#f92672">=</span> require(<span style="color:#e6db74">&#39;mod2&#39;</span>)  <span style="color:#75715e">-- Prints Hi!</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">local</span> b <span style="color:#f92672">=</span> require(<span style="color:#e6db74">&#39;mod2&#39;</span>)  <span style="color:#75715e">-- Doesn&#39;t print; a=b.</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">-- dofile is like require without caching:</span>
</span></span><span style="display:flex;"><span>dofile(<span style="color:#e6db74">&#39;mod2.lua&#39;</span>)  <span style="color:#75715e">--&gt; Hi!</span>
</span></span><span style="display:flex;"><span>dofile(<span style="color:#e6db74">&#39;mod2.lua&#39;</span>)  <span style="color:#75715e">--&gt; Hi! (runs it again)</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">-- loadfile loads a lua file but doesn&#39;t run it yet.</span>
</span></span><span style="display:flex;"><span>f <span style="color:#f92672">=</span> loadfile(<span style="color:#e6db74">&#39;mod2.lua&#39;</span>)  <span style="color:#75715e">-- Call f() to run it.</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">-- load is loadfile for strings.</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">-- (loadstring is deprecated, use load instead)</span>
</span></span><span style="display:flex;"><span>g <span style="color:#f92672">=</span> load(<span style="color:#e6db74">&#39;print(343)&#39;</span>)  <span style="color:#75715e">-- Returns a function.</span>
</span></span><span style="display:flex;"><span>g()  <span style="color:#75715e">-- Prints out 343; nothing printed before now.</span></span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><h2 id="misc">
  <a class="anchor inpage" href="#misc">##</a>misc</h2>
<h3 id="comment">
  <a class="anchor inpage" href="#comment">###</a>comment</h3>
<details open>
    <summary>shell</summary><pre
        class="chroma codeblock"
      ><code class="language-shell" data-lang="shell"
          ><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>-- Two dashes start a one-line comment.
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>--<span style="color:#f92672">[[</span>
</span></span><span style="display:flex;"><span>     Adding two <span style="color:#f92672">[</span><span style="color:#e6db74">&#39;s and ]&#39;</span>s makes it a
</span></span><span style="display:flex;"><span>     multi-line comment.
</span></span><span style="display:flex;"><span>--<span style="color:#f92672">]]</span></span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><h2 id="ref">
  <a class="anchor inpage" href="#ref">##</a>ref</h2>
<p>
</p>
<details open>
    <summary>lua</summary><pre
        class="chroma codeblock"
      ><code class="language-lua" data-lang="lua"
          ><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">----------------------------------------------------</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">-- 1. Variables and flow control.</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">----------------------------------------------------</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">-- Blocks are denoted with keywords like do/end:</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">while</span> num <span style="color:#f92672">&lt;</span> <span style="color:#ae81ff">50</span> <span style="color:#66d9ef">do</span>
</span></span><span style="display:flex;"><span>  num <span style="color:#f92672">=</span> num <span style="color:#f92672">+</span> <span style="color:#ae81ff">1</span>  <span style="color:#75715e">-- No ++ or += type operators.</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">end</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">-- If clauses:</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">----------------------------------------------------</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">-- 2. Functions.</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">----------------------------------------------------</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">----------------------------------------------------</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">-- 3. Tables.</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">----------------------------------------------------</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">-- Tables = Lua&#39;s only compound data structure;</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">--          they are associative arrays.</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">-- Similar to php arrays or js objects, they are</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">-- hash-lookup dicts that can also be used as lists.</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">-- Using tables as dictionaries / maps:</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">-- Dict literals have string keys by default:</span>
</span></span><span style="display:flex;"><span>t <span style="color:#f92672">=</span> {key1 <span style="color:#f92672">=</span> <span style="color:#e6db74">&#39;value1&#39;</span>, key2 <span style="color:#f92672">=</span> <span style="color:#66d9ef">false</span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">-- String keys can use js-like dot notation:</span>
</span></span><span style="display:flex;"><span>print(t.key1)  <span style="color:#75715e">-- Prints &#39;value1&#39;.</span>
</span></span><span style="display:flex;"><span>t.newKey <span style="color:#f92672">=</span> {}  <span style="color:#75715e">-- Adds a new key/value pair.</span>
</span></span><span style="display:flex;"><span>t.key2 <span style="color:#f92672">=</span> <span style="color:#66d9ef">nil</span>   <span style="color:#75715e">-- Removes key2 from the table.</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">-- Literal notation for any (non-nil) value as key:</span>
</span></span><span style="display:flex;"><span>u <span style="color:#f92672">=</span> {[<span style="color:#e6db74">&#39;@!#&#39;</span>] <span style="color:#f92672">=</span> <span style="color:#e6db74">&#39;qbert&#39;</span>, [{}] <span style="color:#f92672">=</span> <span style="color:#ae81ff">1729</span>, [<span style="color:#ae81ff">6.28</span>] <span style="color:#f92672">=</span> <span style="color:#e6db74">&#39;tau&#39;</span>}
</span></span><span style="display:flex;"><span>print(u[<span style="color:#ae81ff">6.28</span>])  <span style="color:#75715e">-- prints &#34;tau&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">-- Key matching is basically by value for numbers</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">-- and strings, but by identity for tables.</span>
</span></span><span style="display:flex;"><span>a <span style="color:#f92672">=</span> u[<span style="color:#e6db74">&#39;@!#&#39;</span>]  <span style="color:#75715e">-- Now a = &#39;qbert&#39;.</span>
</span></span><span style="display:flex;"><span>b <span style="color:#f92672">=</span> u[{}]     <span style="color:#75715e">-- We might expect 1729, but it&#39;s nil:</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">-- b = nil since the lookup fails. It fails</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">-- because the key we used is not the same object</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">-- as the one used to store the original value. So</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">-- strings &amp; numbers are more portable keys.</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">-- A one-table-param function call needs no parens:</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">function</span> <span style="color:#a6e22e">h</span>(x) print(x.key1) <span style="color:#66d9ef">end</span>
</span></span><span style="display:flex;"><span>h{key1 <span style="color:#f92672">=</span> <span style="color:#e6db74">&#39;Sonmi~451&#39;</span>}  <span style="color:#75715e">-- Prints &#39;Sonmi~451&#39;.</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">for</span> key, val <span style="color:#66d9ef">in</span> pairs(u) <span style="color:#66d9ef">do</span>  <span style="color:#75715e">-- Table iteration.</span>
</span></span><span style="display:flex;"><span>  print(key, val)
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">end</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">-- _G is a special table of all globals.</span>
</span></span><span style="display:flex;"><span>print(_G[<span style="color:#e6db74">&#39;_G&#39;</span>] <span style="color:#f92672">==</span> _G)  <span style="color:#75715e">-- Prints &#39;true&#39;.</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">-- Using tables as lists / arrays:</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">-- List literals implicitly set up int keys:</span>
</span></span><span style="display:flex;"><span>v <span style="color:#f92672">=</span> {<span style="color:#e6db74">&#39;value1&#39;</span>, <span style="color:#e6db74">&#39;value2&#39;</span>, <span style="color:#ae81ff">1.21</span>, <span style="color:#e6db74">&#39;gigawatts&#39;</span>}
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">for</span> i <span style="color:#f92672">=</span> <span style="color:#ae81ff">1</span>, <span style="color:#f92672">#</span>v <span style="color:#66d9ef">do</span>  <span style="color:#75715e">-- #v is the size of v for lists.</span>
</span></span><span style="display:flex;"><span>  print(v[i])  <span style="color:#75715e">-- Indices start at 1 !! SO CRAZY!</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">end</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">-- A &#39;list&#39; is not a real type. v is just a table</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">-- with consecutive integer keys, treated as a list.</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">----------------------------------------------------</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">-- 3.1 Metatables and metamethods.</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">----------------------------------------------------</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">-- A table can have a metatable that gives the table</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">-- operator-overloadish behavior. Later we&#39;ll see</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">-- how metatables support js-prototype behavior.</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>f1 <span style="color:#f92672">=</span> {a <span style="color:#f92672">=</span> <span style="color:#ae81ff">1</span>, b <span style="color:#f92672">=</span> <span style="color:#ae81ff">2</span>}  <span style="color:#75715e">-- Represents the fraction a/b.</span>
</span></span><span style="display:flex;"><span>f2 <span style="color:#f92672">=</span> {a <span style="color:#f92672">=</span> <span style="color:#ae81ff">2</span>, b <span style="color:#f92672">=</span> <span style="color:#ae81ff">3</span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">-- This would fail:</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">-- s = f1 + f2</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>metafraction <span style="color:#f92672">=</span> {}
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">function</span> <span style="color:#a6e22e">metafraction</span>.<span style="color:#a6e22e">__add</span>(f1, f2)
</span></span><span style="display:flex;"><span>  sum <span style="color:#f92672">=</span> {}
</span></span><span style="display:flex;"><span>  sum.b <span style="color:#f92672">=</span> f1.b <span style="color:#f92672">*</span> f2.b
</span></span><span style="display:flex;"><span>  sum.a <span style="color:#f92672">=</span> f1.a <span style="color:#f92672">*</span> f2.b <span style="color:#f92672">+</span> f2.a <span style="color:#f92672">*</span> f1.b
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">return</span> sum
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">end</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>setmetatable(f1, metafraction)
</span></span><span style="display:flex;"><span>setmetatable(f2, metafraction)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>s <span style="color:#f92672">=</span> f1 <span style="color:#f92672">+</span> f2  <span style="color:#75715e">-- call __add(f1, f2) on f1&#39;s metatable</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">-- f1, f2 have no key for their metatable, unlike</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">-- prototypes in js, so you must retrieve it as in</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">-- getmetatable(f1). The metatable is a normal table</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">-- with keys that Lua knows about, like __add.</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">-- But the next line fails since s has no metatable:</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">-- t = s + s</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">-- Class-like patterns given below would fix this.</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">-- An __index on a metatable overloads dot lookups:</span>
</span></span><span style="display:flex;"><span>defaultFavs <span style="color:#f92672">=</span> {animal <span style="color:#f92672">=</span> <span style="color:#e6db74">&#39;gru&#39;</span>, food <span style="color:#f92672">=</span> <span style="color:#e6db74">&#39;donuts&#39;</span>}
</span></span><span style="display:flex;"><span>myFavs <span style="color:#f92672">=</span> {food <span style="color:#f92672">=</span> <span style="color:#e6db74">&#39;pizza&#39;</span>}
</span></span><span style="display:flex;"><span>setmetatable(myFavs, {__index <span style="color:#f92672">=</span> defaultFavs})
</span></span><span style="display:flex;"><span>eatenBy <span style="color:#f92672">=</span> myFavs.animal  <span style="color:#75715e">-- works! thanks, metatable</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">-- Direct table lookups that fail will retry using</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">-- the metatable&#39;s __index value, and this recurses.</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">-- An __index value can also be a function(tbl, key)</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">-- for more customized lookups.</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">-- Values of __index,add, .. are called metamethods.</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">-- Full list. Here a is a table with the metamethod.</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">-- __add(a, b)                     for a + b</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">-- __sub(a, b)                     for a - b</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">-- __mul(a, b)                     for a * b</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">-- __div(a, b)                     for a / b</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">-- __mod(a, b)                     for a % b</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">-- __pow(a, b)                     for a ^ b</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">-- __unm(a)                        for -a</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">-- __concat(a, b)                  for a .. b</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">-- __len(a)                        for #a</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">-- __eq(a, b)                      for a == b</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">-- __lt(a, b)                      for a &lt; b</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">-- __le(a, b)                      for a &lt;= b</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">-- __index(a, b)  &lt;fn or a table&gt;  for a.b</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">-- __newindex(a, b, c)             for a.b = c</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">-- __call(a, ...)                  for a(...)</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">----------------------------------------------------</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">-- 3.2 Class-like tables and inheritance.</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">----------------------------------------------------</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">-- Classes aren&#39;t built in; there are different ways</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">-- to make them using tables and metatables.</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">----------------------------------------------------</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">-- 4. Modules.</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">----------------------------------------------------</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">--[[ I&#39;m commenting out this section so the rest of
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">--   this script remains runnable.
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">-- Suppose the file mod.lua looks like this:
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">local M = {}
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">local function sayMyName()
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">  print(&#39;Hrunkner&#39;)
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">end
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">function M.sayHello()
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">  print(&#39;Why hello there&#39;)
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">  sayMyName()
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">end
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">return M
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">-- Another file can use mod.lua&#39;s functionality:
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">local mod = require(&#39;mod&#39;)  -- Run the file mod.lua.
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">-- require is the standard way to include modules.
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">-- require acts like:     (if not cached; see below)
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">local mod = (function ()
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">  &lt;contents of mod.lua&gt;
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">end)()
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">-- It&#39;s like mod.lua is a function body, so that
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">-- locals inside mod.lua are invisible outside it.
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">-- This works because mod here = M in mod.lua:
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">mod.sayHello() -- Prints: Why hello there Hrunkner
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">-- This is wrong; sayMyName only exists in mod.lua:
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">mod.sayMyName()  -- error
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">-- require&#39;s return values are cached so a file is
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">-- run at most once, even when require&#39;d many times.
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">-- Suppose mod2.lua contains &#34;print(&#39;Hi!&#39;)&#34;.
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">local a = require(&#39;mod2&#39;)  -- Prints Hi!
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">local b = require(&#39;mod2&#39;)  -- Doesn&#39;t print; a=b.
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">-- dofile is like require without caching:
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">dofile(&#39;mod2.lua&#39;)  --&gt; Hi!
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">dofile(&#39;mod2.lua&#39;)  --&gt; Hi! (runs it again)
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">-- loadfile loads a lua file but doesn&#39;t run it yet.
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">f = loadfile(&#39;mod2.lua&#39;)  -- Call f() to run it.
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">-- load is loadfile for strings.
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">-- (loadstring is deprecated, use load instead)
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">g = load(&#39;print(343)&#39;)  -- Returns a function.
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">g()  -- Prints out 343; nothing printed before now.
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">--]]</span></span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script>]]></content:encoded></item><item><title>awk</title><link>https://hiraethecho.github.io/docs/dev/awk/</link><pubDate>Mon, 05 May 2025 00:00:00 +0000</pubDate><author>wyz2016zxc@outlook.com(Hiraeth)</author><guid>https://hiraethecho.github.io/docs/dev/awk/</guid><description>&lt;h1 id="awk"&gt;
&lt;a class="anchor inpage" href="#awk"&gt;#&lt;/a&gt;awk&lt;/h1&gt;
&lt;h2 id="tldr"&gt;
&lt;a class="anchor inpage" href="#tldr"&gt;##&lt;/a&gt;tldr&lt;/h2&gt;
&lt;p&gt;A versatile programming language for working on files.
More information:
.&lt;/p&gt;
&lt;p&gt;Print the fifth column (a.k.a. field) in a space-separated file:&lt;/p&gt;
&lt;details open&gt;
&lt;summary&gt;TEXT&lt;/summary&gt;&lt;pre
class="codeblock"
&gt;&lt;code class="language-" data-lang=""&gt;awk &amp;#39;{print $5}&amp;#39; path/to/file&lt;/code&gt;&lt;button onclick="copyCode(this)" class="copybtn"&gt;copy&lt;/button&gt;&lt;/pre&gt;&lt;/details&gt;
&lt;script&gt;
function copyCode(btn) {
const code = btn.previousElementSibling.textContent.trim();
navigator.clipboard.writeText(code).then(() =&gt; {
btn.innerText = "copied";
setTimeout(() =&gt; (btn.innerText = "copy"), 2000);
});
}
&lt;/script&gt;&lt;p&gt;Print the second column of the lines containing &amp;ldquo;foo&amp;rdquo; in a space-separated file:&lt;/p&gt;
&lt;details open&gt;
&lt;summary&gt;TEXT&lt;/summary&gt;&lt;pre
class="codeblock"
&gt;&lt;code class="language-" data-lang=""&gt;awk &amp;#39;/foo/ {print $2}&amp;#39; path/to/file&lt;/code&gt;&lt;button onclick="copyCode(this)" class="copybtn"&gt;copy&lt;/button&gt;&lt;/pre&gt;&lt;/details&gt;
&lt;script&gt;
function copyCode(btn) {
const code = btn.previousElementSibling.textContent.trim();
navigator.clipboard.writeText(code).then(() =&gt; {
btn.innerText = "copied";
setTimeout(() =&gt; (btn.innerText = "copy"), 2000);
});
}
&lt;/script&gt;&lt;p&gt;Print the last column of each line in a file, using a comma (instead of space) as a field separator:&lt;/p&gt;</description><content:encoded><![CDATA[<h1 id="awk">
  <a class="anchor inpage" href="#awk">#</a>awk</h1>
<h2 id="tldr">
  <a class="anchor inpage" href="#tldr">##</a>tldr</h2>
<p>A versatile programming language for working on files.
More information: 
.</p>
<p>Print the fifth column (a.k.a. field) in a space-separated file:</p>
<details open>
    <summary>TEXT</summary><pre
        class="codeblock"
      ><code class="language-" data-lang="">awk &#39;{print $5}&#39; path/to/file</code><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><p>Print the second column of the lines containing &ldquo;foo&rdquo; in a space-separated file:</p>
<details open>
    <summary>TEXT</summary><pre
        class="codeblock"
      ><code class="language-" data-lang="">awk &#39;/foo/ {print $2}&#39; path/to/file</code><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><p>Print the last column of each line in a file, using a comma (instead of space) as a field separator:</p>
<details open>
    <summary>TEXT</summary><pre
        class="codeblock"
      ><code class="language-" data-lang="">awk -F &#39;,&#39; &#39;{print $NF}&#39; path/to/file</code><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><p>Sum the values in the first column of a file and print the total:</p>
<details open>
    <summary>TEXT</summary><pre
        class="codeblock"
      ><code class="language-" data-lang="">awk &#39;{s&#43;=$1} END {print s}&#39; path/to/file</code><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><p>Print every third line starting from the first line:</p>
<details open>
    <summary>TEXT</summary><pre
        class="codeblock"
      ><code class="language-" data-lang="">awk &#39;NR%3==1&#39; path/to/file</code><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><p>Print different values based on conditions:</p>
<details open>
    <summary>TEXT</summary><pre
        class="codeblock"
      ><code class="language-" data-lang="">awk &#39;{if ($1 == &#34;foo&#34;) print &#34;Exact match foo&#34;; else if ($1 ~ &#34;bar&#34;) print &#34;Partial match bar&#34;; else print &#34;Baz&#34;}&#39; path/to/file</code><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><p>Print all the lines which the 10th column value is between a min and a max:</p>
<details open>
    <summary>TEXT</summary><pre
        class="codeblock"
      ><code class="language-" data-lang="">awk &#39;($10 &gt;= min_value &amp;&amp; $10 &lt;= max_value)&#39;</code><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><p>Print table of users with UID &gt;=1000 with header and formatted output, using colon as separator (<code>%-20s</code> mean: 20 left-align string characters, <code>%6s</code> means: 6 right-align string characters):</p>
<details open>
    <summary>TEXT</summary><pre
        class="codeblock"
      ><code class="language-" data-lang="">awk &#39;BEGIN {FS=&#34;:&#34;;printf &#34;%-20s %6s %25s\n&#34;, &#34;Name&#34;, &#34;UID&#34;, &#34;Shell&#34;} $4 &gt;= 1000 {printf &#34;%-20s %6d %25s\n&#34;, $1, $4, $7}&#39; /etc/passwd</code><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><h2 id="getting-started">
  <a class="anchor inpage" href="#getting-started">##</a>Getting Started</h2>
<h3 id="have-a-try">
  <a class="anchor inpage" href="#have-a-try">###</a>Have a try</h3>
<details open>
    <summary>shell</summary><pre
        class="chroma codeblock"
      ><code class="language-shell" data-lang="shell"
          ><span style="display:flex;"><span>$ awk -F: <span style="color:#e6db74">&#39;{print $1, $NF}&#39;</span> /etc/passwd</span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><table>
  <thead>
      <tr>
          <th>-</th>
          <th>-</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><code>-F:</code></td>
          <td>Colon as a separator</td>
      </tr>
      <tr>
          <td><code>{...}</code></td>
          <td>Awk program</td>
      </tr>
      <tr>
          <td><code>print</code></td>
          <td>Prints the current record</td>
      </tr>
      <tr>
          <td><code>$1</code></td>
          <td>First field</td>
      </tr>
      <tr>
          <td><code>$NF</code></td>
          <td>Last field</td>
      </tr>
      <tr>
          <td><code>/etc/passwd</code></td>
          <td>Input data file</td>
      </tr>
  </tbody>
</table>
<h3 id="awk-program">
  <a class="anchor inpage" href="#awk-program">###</a>Awk program</h3>
<details open>
    <summary>TEXT</summary><pre
        class="codeblock"
      ><code class="language-" data-lang="">BEGIN          {&lt;initializations&gt;}
   &lt;pattern 1&gt; {&lt;program actions&gt;}
   &lt;pattern 2&gt; {&lt;program actions&gt;}
   ...
END            {&lt; final actions &gt;}</code><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><h4 id="example">
  <a class="anchor inpage" href="#example">####</a>Example</h4>
<details open>
    <summary>TEXT</summary><pre
        class="codeblock"
      ><code class="language-" data-lang="">awk &#39;
    BEGIN { print &#34;\n&gt;&gt;&gt;Start&#34; }
    !/(login|shutdown)/ { print NR, $0 }
    END { print &#34;&lt;&lt;&lt;END\n&#34; }
&#39; /etc/passwd</code><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><h3 id="variables">
  <a class="anchor inpage" href="#variables">###</a>Variables</h3>
<details open>
    <summary>bash</summary><pre
        class="chroma codeblock"
      ><code class="language-bash" data-lang="bash"
          ><span style="display:flex;"><span>          $1      $2/<span style="color:#66d9ef">$(</span>NF-1<span style="color:#66d9ef">)</span>    $3/$NF
</span></span><span style="display:flex;"><span>           ▼          ▼           ▼
</span></span><span style="display:flex;"><span>        ┌──────┬──────────────────┬───────┐
</span></span><span style="display:flex;"><span>$0/NR ▶ │  ID  │  WEBSITE         │  URI  │
</span></span><span style="display:flex;"><span>        ├──────┼──────────────────┼───────┤
</span></span><span style="display:flex;"><span>$0/NR ▶ │  <span style="color:#ae81ff">1</span>   │  cheatsheets.zip │  awk  │
</span></span><span style="display:flex;"><span>        ├──────┼──────────────────┼───────┤
</span></span><span style="display:flex;"><span>$0/NR ▶ │  <span style="color:#ae81ff">2</span>   │  google.com      │  <span style="color:#ae81ff">25</span>   │
</span></span><span style="display:flex;"><span>        └──────┴──────────────────┴───────┘</span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><details open>
    <summary>TEXT</summary><pre
        class="codeblock"
      ><code class="language-" data-lang=""># First and last field
awk -F: &#39;{print $1,$NF}&#39; /etc/passwd

# With line number
awk -F: &#39;{print NR, $0}&#39; /etc/passwd

# Second last field
awk -F: &#39;{print $(NF-1)}&#39; /etc/passwd

# Custom string
awk -F: &#39;{print $1 &#34;=&#34; $6}&#39; /etc/passwd</code><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><h3 id="awk-program-examples">
  <a class="anchor inpage" href="#awk-program-examples">###</a>Awk program examples</h3>
<details open>
    <summary>TEXT</summary><pre
        class="codeblock"
      ><code class="language-" data-lang="">awk &#39;BEGIN {print &#34;hello world&#34;}&#39;        # Prints &#34;hello world&#34;
awk -F: &#39;{print $1}&#39; /etc/passwd         # -F: Specify field separator

# /pattern/ Execute actions only for matched pattern
awk -F: &#39;/root/ {print $1}&#39; /etc/passwd

# BEGIN block is executed once at the start
awk -F: &#39;BEGIN { print &#34;uid&#34;} { print $1 }&#39; /etc/passwd

# END block is executed once at the end
awk -F: &#39;{print $1} END { print &#34;-done-&#34;}&#39; /etc/passwd</code><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><h3 id="conditions">
  <a class="anchor inpage" href="#conditions">###</a>Conditions</h3>
<details open>
    <summary>TEXT</summary><pre
        class="codeblock"
      ><code class="language-" data-lang="">awk -F: &#39;$3&gt;30 {print $1}&#39; /etc/passwd</code><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><h3 id="generate-1000-spaces">
  <a class="anchor inpage" href="#generate-1000-spaces">###</a>Generate 1000 spaces</h3>
<details open>
    <summary>TEXT</summary><pre
        class="codeblock"
      ><code class="language-" data-lang="">awk &#39;BEGIN{
    while (a&#43;&#43; &lt; 1000)
        s=s &#34; &#34;;
    print s
}&#39;</code><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><h3 id="arrays">
  <a class="anchor inpage" href="#arrays">###</a>Arrays</h3>
<details open>
    <summary>TEXT</summary><pre
        class="codeblock"
      ><code class="language-" data-lang="">awk &#39;BEGIN {
   fruits[&#34;mango&#34;] = &#34;yellow&#34;;
   fruits[&#34;orange&#34;] = &#34;orange&#34;
   for(fruit in fruits) {
     print &#34;The color of &#34; fruit &#34; is &#34; fruits[fruit]
   }
}&#39;</code><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><h3 id="functions">
  <a class="anchor inpage" href="#functions">###</a>Functions</h3>
<details open>
    <summary>TEXT</summary><pre
        class="codeblock"
      ><code class="language-" data-lang=""># =&gt; 5
awk &#39;BEGIN{print length(&#34;hello&#34;)}&#39;
# =&gt; HELLO
awk &#39;BEGIN{print toupper(&#34;hello&#34;)}&#39;
# =&gt; hel
awk &#39;BEGIN{print substr(&#34;hello&#34;, 1, 3)}&#39;</code><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><h2 id="awk-variables">
  <a class="anchor inpage" href="#awk-variables">##</a>Awk Variables</h2>
<h3 id="build-in-variables">
  <a class="anchor inpage" href="#build-in-variables">###</a>Build-in variables</h3>
<table>
  <thead>
      <tr>
          <th>-</th>
          <th>-</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><code>$0</code></td>
          <td>Whole line</td>
      </tr>
      <tr>
          <td><code>$1, $2...$NF</code></td>
          <td>First, second… last field</td>
      </tr>
      <tr>
          <td><code>NR</code></td>
          <td><code>N</code>umber of <code>R</code>ecords</td>
      </tr>
      <tr>
          <td><code>NF</code></td>
          <td><code>N</code>umber of <code>F</code>ields</td>
      </tr>
      <tr>
          <td><code>OFS</code></td>
          <td><code>O</code>utput <code>F</code>ield <code>S</code>eparator <br> <em>(default &quot; &ldquo;)</em></td>
      </tr>
      <tr>
          <td><code>FS</code></td>
          <td>input <code>F</code>ield <code>S</code>eparator <br> <em>(default &quot; &ldquo;)</em></td>
      </tr>
      <tr>
          <td><code>ORS</code></td>
          <td><code>O</code>utput <code>R</code>ecord <code>S</code>eparator <br> <em>(default &ldquo;\n&rdquo;)</em></td>
      </tr>
      <tr>
          <td><code>RS</code></td>
          <td>input <code>R</code>ecord <code>S</code>eparator <br> <em>(default &ldquo;\n&rdquo;)</em></td>
      </tr>
      <tr>
          <td><code>FILENAME</code></td>
          <td>Name of the file</td>
      </tr>
  </tbody>
</table>
<h3 id="expressions">
  <a class="anchor inpage" href="#expressions">###</a>Expressions</h3>
<table>
  <thead>
      <tr>
          <th>-</th>
          <th>-</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><code>$1 == &quot;root&quot;</code></td>
          <td>First field equals root</td>
      </tr>
      <tr>
          <td><code>{print $(NF-1)}</code></td>
          <td>Second last field</td>
      </tr>
      <tr>
          <td><code>NR!=1{print $0}</code></td>
          <td>From 2nd record</td>
      </tr>
      <tr>
          <td><code>NR &gt; 3</code></td>
          <td>From 4th record</td>
      </tr>
      <tr>
          <td><code>NR == 1</code></td>
          <td>First record</td>
      </tr>
      <tr>
          <td><code>END{print NR}</code></td>
          <td>Total records</td>
      </tr>
      <tr>
          <td><code>BEGIN{print OFMT}</code></td>
          <td>Output format</td>
      </tr>
      <tr>
          <td><code>{print NR, $0}</code></td>
          <td>Line number</td>
      </tr>
      <tr>
          <td><code>{print NR &quot;	&quot; $0}</code></td>
          <td>Line number (tab)</td>
      </tr>
      <tr>
          <td><code>{$1 = NR; print}</code></td>
          <td>Replace 1st field with line number</td>
      </tr>
      <tr>
          <td><code>$NF &gt; 4</code></td>
          <td>Last field &gt; 4</td>
      </tr>
      <tr>
          <td><code>NR % 2 == 0</code></td>
          <td>Even records</td>
      </tr>
      <tr>
          <td><code>NR==10, NR==20</code></td>
          <td>Records 10 to 20</td>
      </tr>
      <tr>
          <td><code>BEGIN{print ARGC}</code></td>
          <td>Total arguments</td>
      </tr>
      <tr>
          <td><code>ORS=NR%5?&quot;,&quot;:&quot;\n&quot;</code></td>
          <td>Concatenate records</td>
      </tr>
  </tbody>
</table>
<h3 id="examples">
  <a class="anchor inpage" href="#examples">###</a>Examples</h3>
<p>Print sum and average</p>
<details open>
    <summary>TEXT</summary><pre
        class="codeblock"
      ><code class="language-" data-lang="">awk -F: &#39;{sum &#43;= $3}
     END { print sum, sum/NR }
&#39; /etc/passwd</code><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><p>Printing parameters</p>
<details open>
    <summary>TEXT</summary><pre
        class="codeblock"
      ><code class="language-" data-lang="">awk &#39;BEGIN {
    for (i = 1; i &lt; ARGC; i&#43;&#43;)
        print ARGV[i] }&#39; a b c</code><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><p>Output field separator as a comma</p>
<details open>
    <summary>TEXT</summary><pre
        class="codeblock"
      ><code class="language-" data-lang="">awk &#39;BEGIN { FS=&#34;:&#34;;OFS=&#34;,&#34;}
    {print $1,$2,$3,$4}&#39; /etc/passwd</code><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><p>Position of match</p>
<details open>
    <summary>TEXT</summary><pre
        class="codeblock"
      ><code class="language-" data-lang="">awk &#39;BEGIN {
    if (match(&#34;One Two Three&#34;, &#34;Tw&#34;))
        print RSTART }&#39;</code><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><p>Length of match</p>
<details open>
    <summary>TEXT</summary><pre
        class="codeblock"
      ><code class="language-" data-lang="">awk &#39;BEGIN {
    if (match(&#34;One Two Three&#34;, &#34;re&#34;))
        print RLENGTH }&#39;</code><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><h3 id="environment-variables">
  <a class="anchor inpage" href="#environment-variables">###</a>Environment Variables</h3>
<table>
  <thead>
      <tr>
          <th>-</th>
          <th>-</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><code>ARGC</code></td>
          <td>Number or arguments</td>
      </tr>
      <tr>
          <td><code>ARGV</code></td>
          <td>Array of arguments</td>
      </tr>
      <tr>
          <td><code>FNR</code></td>
          <td><code>F</code>ile <code>N</code>umber of <code>R</code>ecords</td>
      </tr>
      <tr>
          <td><code>OFMT</code></td>
          <td>Format for numbers <br> <em>(default &ldquo;%.6g&rdquo;)</em></td>
      </tr>
      <tr>
          <td><code>RSTART</code></td>
          <td>Location in the string</td>
      </tr>
      <tr>
          <td><code>RLENGTH</code></td>
          <td>Length of match</td>
      </tr>
      <tr>
          <td><code>SUBSEP</code></td>
          <td>Multi-dimensional array separator <br> <em>(default &ldquo;\034&rdquo;)</em></td>
      </tr>
      <tr>
          <td><code>ARGIND</code></td>
          <td>Argument Index</td>
      </tr>
  </tbody>
</table>
<h3 id="gnu-awk-only">
  <a class="anchor inpage" href="#gnu-awk-only">###</a>GNU awk only</h3>
<table>
  <thead>
      <tr>
          <th>-</th>
          <th>-</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><code>ENVIRON</code></td>
          <td>Environment variables</td>
      </tr>
      <tr>
          <td><code>IGNORECASE</code></td>
          <td>Ignore case</td>
      </tr>
      <tr>
          <td><code>CONVFMT</code></td>
          <td>Conversion format</td>
      </tr>
      <tr>
          <td><code>ERRNO</code></td>
          <td>System errors</td>
      </tr>
      <tr>
          <td><code>FIELDWIDTHS</code></td>
          <td>Fixed width fields</td>
      </tr>
  </tbody>
</table>
<h3 id="defining-variable">
  <a class="anchor inpage" href="#defining-variable">###</a>Defining variable</h3>
<details open>
    <summary>TEXT</summary><pre
        class="codeblock"
      ><code class="language-" data-lang="">awk -v var1=&#34;Hello&#34; -v var2=&#34;Wold&#34; &#39;
    END {print var1, var2}
&#39; &lt;/dev/null</code><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><h4 id="use-shell-variables">
  <a class="anchor inpage" href="#use-shell-variables">####</a>Use shell variables</h4>
<details open>
    <summary>TEXT</summary><pre
        class="codeblock"
      ><code class="language-" data-lang="">awk -v varName=&#34;$PWD&#34; &#39;
    END {print varName}&#39; &lt;/dev/null</code><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><h2 id="awk-operators">
  <a class="anchor inpage" href="#awk-operators">##</a>Awk Operators</h2>
<h3 id="operators">
  <a class="anchor inpage" href="#operators">###</a>Operators</h3>
<table>
  <thead>
      <tr>
          <th>-</th>
          <th>-</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><code>{print $1}</code></td>
          <td>First field</td>
      </tr>
      <tr>
          <td><code>$2 == &quot;foo&quot;</code></td>
          <td>Equals</td>
      </tr>
      <tr>
          <td><code>$2 != &quot;foo&quot;</code></td>
          <td>Not equals</td>
      </tr>
      <tr>
          <td><code>&quot;foo&quot; in array</code></td>
          <td>In array</td>
      </tr>
  </tbody>
</table>
<h4 id="regular-expression">
  <a class="anchor inpage" href="#regular-expression">####</a>Regular expression</h4>
<table>
  <thead>
      <tr>
          <th>-</th>
          <th>-</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><code>/regex/</code></td>
          <td>Line matches</td>
      </tr>
      <tr>
          <td><code>!/regex/</code></td>
          <td>Line not matches</td>
      </tr>
      <tr>
          <td><code>$1 ~ /regex/</code></td>
          <td>Field matches</td>
      </tr>
      <tr>
          <td><code>$1 !~ /regex/</code></td>
          <td>Field not matches</td>
      </tr>
  </tbody>
</table>
<h4 id="more-conditions">
  <a class="anchor inpage" href="#more-conditions">####</a>More conditions</h4>
<table>
  <thead>
      <tr>
          <th>-</th>
          <th>-</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><code>($2 &lt;= 4 || $3 &lt; 20)</code></td>
          <td>Or</td>
      </tr>
      <tr>
          <td><code>($1 == 4 &amp;&amp; $3 &lt; 20)</code></td>
          <td>And</td>
      </tr>
  </tbody>
</table>
<h3 id="operations">
  <a class="anchor inpage" href="#operations">###</a>Operations</h3>
<h4 id="arithmetic-operations">
  <a class="anchor inpage" href="#arithmetic-operations">####</a>Arithmetic operations</h4>
<ul>
<li><code>+</code></li>
<li><code>-</code></li>
<li><code>*</code></li>
<li><code>/</code></li>
<li><code>%</code></li>
<li><code>++</code></li>
<li><code>--</code></li>
</ul>
<h4 id="shorthand-assignments">
  <a class="anchor inpage" href="#shorthand-assignments">####</a>Shorthand assignments</h4>
<ul>
<li><code>+=</code></li>
<li><code>-=</code></li>
<li><code>*=</code></li>
<li><code>/=</code></li>
<li><code>%=</code></li>
</ul>
<h4 id="comparison-operators">
  <a class="anchor inpage" href="#comparison-operators">####</a>Comparison operators</h4>
<ul>
<li><code>==</code></li>
<li><code>!=</code></li>
<li><code>&lt;</code></li>
<li><code>&gt;</code></li>
<li><code>&lt;=</code></li>
<li><code>&gt;=</code></li>
</ul>
<h3 id="examples-1">
  <a class="anchor inpage" href="#examples-1">###</a>Examples</h3>
<details open>
    <summary>TEXT</summary><pre
        class="codeblock"
      ><code class="language-" data-lang="">awk &#39;BEGIN {
    if (&#34;foo&#34; ~ &#34;^fo&#43;$&#34;)
        print &#34;Fooey!&#34;;
}&#39;</code><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><h4 id="not-match">
  <a class="anchor inpage" href="#not-match">####</a>Not match</h4>
<details open>
    <summary>TEXT</summary><pre
        class="codeblock"
      ><code class="language-" data-lang="">awk &#39;BEGIN {
    if (&#34;boo&#34; !~ &#34;^fo&#43;$&#34;)
        print &#34;Boo!&#34;;
}&#39;</code><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><h4 id="if-in-array">
  <a class="anchor inpage" href="#if-in-array">####</a>if in array</h4>
<details open>
    <summary>TEXT</summary><pre
        class="codeblock"
      ><code class="language-" data-lang="">awk &#39;BEGIN {
    assoc[&#34;foo&#34;] = &#34;bar&#34;;
    assoc[&#34;bar&#34;] = &#34;baz&#34;;
    if (&#34;foo&#34; in assoc)
        print &#34;Fooey!&#34;;
}&#39;</code><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><h2 id="awk-functions">
  <a class="anchor inpage" href="#awk-functions">##</a>Awk Functions</h2>
<h3 id="common-functions">
  <a class="anchor inpage" href="#common-functions">###</a>Common functions</h3>
<table>
  <thead>
      <tr>
          <th>Function</th>
          <th>Description</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><code>index(s,t)</code></td>
          <td>Position in string s where string t occurs, 0 if not found</td>
      </tr>
      <tr>
          <td><code>length(s)</code></td>
          <td>Length of string s (or $0 if no arg)</td>
      </tr>
      <tr>
          <td><code>rand</code></td>
          <td>Random number between 0 and 1</td>
      </tr>
      <tr>
          <td><code>substr(s,index,len)</code></td>
          <td>Return len-char substring of s that begins at index (counted from 1)</td>
      </tr>
      <tr>
          <td><code>srand</code></td>
          <td>Set seed for rand and return previous seed</td>
      </tr>
      <tr>
          <td><code>int(x)</code></td>
          <td>Truncate x to integer value</td>
      </tr>
      <tr>
          <td><code>split(s,a,fs)</code></td>
          <td>Split string s into array a split by fs, returning length of a</td>
      </tr>
      <tr>
          <td><code>match(s,r)</code></td>
          <td>Position in string s where regex r occurs, or 0 if not found</td>
      </tr>
      <tr>
          <td><code>sub(r,t,s)</code></td>
          <td>Substitute t for first occurrence of regex r in string s (or $0 if s not given)</td>
      </tr>
      <tr>
          <td><code>gsub(r,t,s)</code></td>
          <td>Substitute t for all occurrences of regex r in string s</td>
      </tr>
      <tr>
          <td><code>system(cmd)</code></td>
          <td>Execute cmd and return exit status</td>
      </tr>
      <tr>
          <td><code>tolower(s)</code></td>
          <td>String s to lowercase</td>
      </tr>
      <tr>
          <td><code>toupper(s)</code></td>
          <td>String s to uppercase</td>
      </tr>
      <tr>
          <td><code>getline</code></td>
          <td>Set $0 to next input record from current input file.</td>
      </tr>
  </tbody>
</table>
<h3 id="user-defined-function">
  <a class="anchor inpage" href="#user-defined-function">###</a>User defined function</h3>
<details open>
    <summary>TEXT</summary><pre
        class="codeblock"
      ><code class="language-" data-lang="">awk &#39;
    # Returns minimum number
    function find_min(num1, num2){
       if (num1 &lt; num2)
       return num1
       return num2
    }
    # Returns maximum number
    function find_max(num1, num2){
       if (num1 &gt; num2)
       return num1
       return num2
    }
    # Main function
    function main(num1, num2){
       result = find_min(num1, num2)
       print &#34;Minimum =&#34;, result

       result = find_max(num1, num2)
       print &#34;Maximum =&#34;, result
    }
    # Script execution starts here
    BEGIN {
       main(10, 60)
    }
&#39;</code><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><h2 id="awk-arrays">
  <a class="anchor inpage" href="#awk-arrays">##</a>Awk Arrays</h2>
<h3 id="array-with-index">
  <a class="anchor inpage" href="#array-with-index">###</a>Array with index</h3>
<details open>
    <summary>TEXT</summary><pre
        class="codeblock"
      ><code class="language-" data-lang="">awk &#39;BEGIN {
    arr[0] = &#34;foo&#34;;
    arr[1] = &#34;bar&#34;;
    print(arr[0]); # =&gt; foo
    delete arr[0];
    print(arr[0]); # =&gt; &#34;&#34;
}&#39;</code><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><h3 id="array-with-key">
  <a class="anchor inpage" href="#array-with-key">###</a>Array with key</h3>
<details open>
    <summary>TEXT</summary><pre
        class="codeblock"
      ><code class="language-" data-lang="">awk &#39;BEGIN {
    assoc[&#34;foo&#34;] = &#34;bar&#34;;
    assoc[&#34;bar&#34;] = &#34;baz&#34;;
    print(&#34;baz&#34; in assoc); # =&gt; 0
    print(&#34;foo&#34; in assoc); # =&gt; 1
}&#39;</code><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><h3 id="array-with-split">
  <a class="anchor inpage" href="#array-with-split">###</a>Array with split</h3>
<details open>
    <summary>TEXT</summary><pre
        class="codeblock"
      ><code class="language-" data-lang="">awk &#39;BEGIN {
    split(&#34;foo:bar:baz&#34;, arr, &#34;:&#34;);
    for (key in arr)
        print arr[key];
}&#39;</code><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><h3 id="array-with-asort">
  <a class="anchor inpage" href="#array-with-asort">###</a>Array with asort</h3>
<details open>
    <summary>TEXT</summary><pre
        class="codeblock"
      ><code class="language-" data-lang="">awk &#39;BEGIN {
    arr[0] = 3
    arr[1] = 2
    arr[2] = 4
    n = asort(arr)
    for (i = 1; i &lt;= n ; i&#43;&#43;)
        print(arr[i])
}&#39;</code><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><h3 id="multi-dimensional">
  <a class="anchor inpage" href="#multi-dimensional">###</a>Multi-dimensional</h3>
<details open>
    <summary>TEXT</summary><pre
        class="codeblock"
      ><code class="language-" data-lang="">awk &#39;BEGIN {
    multidim[0,0] = &#34;foo&#34;;
    multidim[0,1] = &#34;bar&#34;;
    multidim[1,0] = &#34;baz&#34;;
    multidim[1,1] = &#34;boo&#34;;
}&#39;</code><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><h3 id="multi-dimensional-iteration">
  <a class="anchor inpage" href="#multi-dimensional-iteration">###</a>Multi-dimensional iteration</h3>
<details open>
    <summary>TEXT</summary><pre
        class="codeblock"
      ><code class="language-" data-lang="">awk &#39;BEGIN {
    array[1,2]=3;
    array[2,3]=5;
    for (comb in array) {
        split(comb,sep,SUBSEP);
        print sep[1], sep[2],
        array[sep[1],sep[2]]
    }
}&#39;</code><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><h2 id="awk-conditions">
  <a class="anchor inpage" href="#awk-conditions">##</a>Awk Conditions</h2>
<h3 id="if-else-statement">
  <a class="anchor inpage" href="#if-else-statement">###</a>if-else statement</h3>
<details open>
    <summary>TEXT</summary><pre
        class="codeblock"
      ><code class="language-" data-lang="">awk -v count=2 &#39;BEGIN {
    if (count == 1)
        print &#34;Yes&#34;;
    else
        print &#34;Huh?&#34;;
}&#39;</code><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><h4 id="ternary-operator">
  <a class="anchor inpage" href="#ternary-operator">####</a>Ternary operator</h4>
<details open>
    <summary>TEXT</summary><pre
        class="codeblock"
      ><code class="language-" data-lang="">awk -v count=2 &#39;BEGIN {
    print (count==1) ? &#34;Yes&#34; : &#34;Huh?&#34;;
}&#39;</code><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><h3 id="exists">
  <a class="anchor inpage" href="#exists">###</a>Exists</h3>
<details open>
    <summary>TEXT</summary><pre
        class="codeblock"
      ><code class="language-" data-lang="">awk &#39;BEGIN {
    assoc[&#34;foo&#34;] = &#34;bar&#34;;
    assoc[&#34;bar&#34;] = &#34;baz&#34;;
    if (&#34;foo&#34; in assoc)
        print &#34;Fooey!&#34;;
}&#39;</code><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><h4 id="not-exists">
  <a class="anchor inpage" href="#not-exists">####</a>Not exists</h4>
<details open>
    <summary>TEXT</summary><pre
        class="codeblock"
      ><code class="language-" data-lang="">awk &#39;BEGIN {
    assoc[&#34;foo&#34;] = &#34;bar&#34;;
    assoc[&#34;bar&#34;] = &#34;baz&#34;;
    if (&#34;Huh&#34; in assoc == 0 )
        print &#34;Huh!&#34;;
}&#39;</code><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><h3 id="switch">
  <a class="anchor inpage" href="#switch">###</a>switch</h3>
<details open>
    <summary>TEXT</summary><pre
        class="codeblock"
      ><code class="language-" data-lang="">awk -F: &#39;{
    switch (NR * 2 &#43; 1) {
        case 3:
        case &#34;11&#34;:
            print NR - 1
            break

        case /2[[:digit:]]&#43;/:
            print NR

        default:
            print NR &#43; 1

        case -1:
            print NR * -1
    }
}&#39; /etc/passwd</code><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><h2 id="awk-loops">
  <a class="anchor inpage" href="#awk-loops">##</a>Awk Loops</h2>
<h3 id="fori">
  <a class="anchor inpage" href="#fori">###</a>for&hellip;i</h3>
<details open>
    <summary>TEXT</summary><pre
        class="codeblock"
      ><code class="language-" data-lang="">awk &#39;BEGIN {
    for (i = 0; i &lt; 10; i&#43;&#43;)
        print &#34;i=&#34; i;
}&#39;</code><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><h4 id="powers-of-two-between-1-and-100">
  <a class="anchor inpage" href="#powers-of-two-between-1-and-100">####</a>Powers of two between 1 and 100</h4>
<details open>
    <summary>TEXT</summary><pre
        class="codeblock"
      ><code class="language-" data-lang="">awk &#39;BEGIN {
    for (i = 1; i &lt;= 100; i *= 2)
        print i
}&#39;</code><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><h3 id="forin">
  <a class="anchor inpage" href="#forin">###</a>for&hellip;in</h3>
<details open>
    <summary>TEXT</summary><pre
        class="codeblock"
      ><code class="language-" data-lang="">awk &#39;BEGIN {
    assoc[&#34;key1&#34;] = &#34;val1&#34;
    assoc[&#34;key2&#34;] = &#34;val2&#34;
    for (key in assoc)
        print assoc[key];
}&#39;</code><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><h4 id="arguments">
  <a class="anchor inpage" href="#arguments">####</a>Arguments</h4>
<details open>
    <summary>TEXT</summary><pre
        class="codeblock"
      ><code class="language-" data-lang="">awk &#39;BEGIN {
    for (argnum in ARGV)
        print ARGV[argnum];
}&#39; a b c</code><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><h3 id="examples-2">
  <a class="anchor inpage" href="#examples-2">###</a>Examples</h3>
<h4 id="reverse-records">
  <a class="anchor inpage" href="#reverse-records">####</a>Reverse records</h4>
<details open>
    <summary>TEXT</summary><pre
        class="codeblock"
      ><code class="language-" data-lang="">awk -F: &#39;{ x[NR] = $0 }
    END {
        for (i = NR; i &gt; 0; i--)
        print x[i]
    }
&#39; /etc/passwd</code><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><h4 id="reverse-fields">
  <a class="anchor inpage" href="#reverse-fields">####</a>Reverse fields</h4>
<details open>
    <summary>TEXT</summary><pre
        class="codeblock"
      ><code class="language-" data-lang="">awk -F: &#39;{
    for (i = NF; i &gt; 0; i--)
        printf(&#34;%s &#34;,$i);
    print &#34;&#34;
}&#39; /etc/passwd</code><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><h4 id="sum-by-record">
  <a class="anchor inpage" href="#sum-by-record">####</a>Sum by record</h4>
<details open>
    <summary>TEXT</summary><pre
        class="codeblock"
      ><code class="language-" data-lang="">awk -F: &#39;{
    s=0;
    for (i = 1; i &lt;= NF; i&#43;&#43;)
        s &#43;= $i;
    print s
}&#39; /etc/passwd</code><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><h4 id="sum-whole-file">
  <a class="anchor inpage" href="#sum-whole-file">####</a>Sum whole file</h4>
<details open>
    <summary>TEXT</summary><pre
        class="codeblock"
      ><code class="language-" data-lang="">awk -F: &#39;
    {for (i = 1; i &lt;= NF; i&#43;&#43;)
        s &#43;= $i;
    };
    END{print s}
&#39; /etc/passwd</code><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><h3 id="while">
  <a class="anchor inpage" href="#while">###</a>while</h3>
<details open>
    <summary>TEXT</summary><pre
        class="codeblock"
      ><code class="language-" data-lang="">awk &#39;BEGIN {
    while (a &lt; 10) {
        print &#34;- &#34; &#34; concatenation: &#34; a
        a&#43;&#43;;
    }
}&#39;</code><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><h4 id="dowhile">
  <a class="anchor inpage" href="#dowhile">####</a>do&hellip;while</h4>
<details open>
    <summary>TEXT</summary><pre
        class="codeblock"
      ><code class="language-" data-lang="">awk &#39;{
    i = 1
    do {
        print $0
        i&#43;&#43;
    } while (i &lt;= 5)
}&#39; /etc/passwd</code><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><h3 id="break">
  <a class="anchor inpage" href="#break">###</a>Break</h3>
<details open>
    <summary>TEXT</summary><pre
        class="codeblock"
      ><code class="language-" data-lang="">awk &#39;BEGIN {
    break_num = 5
    for (i = 0; i &lt; 10; i&#43;&#43;) {
        print i
        if (i == break_num)
            break
    }
}&#39;</code><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><h3 id="continue">
  <a class="anchor inpage" href="#continue">###</a>Continue</h3>
<details open>
    <summary>TEXT</summary><pre
        class="codeblock"
      ><code class="language-" data-lang="">awk &#39;BEGIN {
    for (x = 0; x &lt;= 10; x&#43;&#43;) {
        if (x == 5 || x == 6)
            continue
        printf &#34;%d &#34;, x
    }
    print &#34;&#34;
}&#39;</code><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><h2 id="awk-formatted-printing">
  <a class="anchor inpage" href="#awk-formatted-printing">##</a>Awk Formatted Printing</h2>
<h3 id="usage">
  <a class="anchor inpage" href="#usage">###</a>Usage</h3>
<h4 id="right-align">
  <a class="anchor inpage" href="#right-align">####</a>Right align</h4>
<details open>
    <summary>TEXT</summary><pre
        class="codeblock"
      ><code class="language-" data-lang="">awk &#39;BEGIN{printf &#34;|%10s|\n&#34;, &#34;hello&#34;}&#39;

|     hello|</code><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><h4 id="left-align">
  <a class="anchor inpage" href="#left-align">####</a>Left align</h4>
<details open>
    <summary>TEXT</summary><pre
        class="codeblock"
      ><code class="language-" data-lang="">awk &#39;BEGIN{printf &#34;|%-10s|\n&#34;, &#34;hello&#34;}&#39;

|hello     |</code><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><h3 id="common-specifiers">
  <a class="anchor inpage" href="#common-specifiers">###</a>Common specifiers</h3>
<table>
  <thead>
      <tr>
          <th>Character</th>
          <th>Description</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><code>c</code></td>
          <td>ASCII character</td>
      </tr>
      <tr>
          <td><code>d</code></td>
          <td>Decimal integer</td>
      </tr>
      <tr>
          <td><code>e</code>, <code>E</code>, <code>f</code></td>
          <td>Floating-point format</td>
      </tr>
      <tr>
          <td><code>o</code></td>
          <td>Unsigned octal value</td>
      </tr>
      <tr>
          <td><code>s</code></td>
          <td>String</td>
      </tr>
      <tr>
          <td><code>%</code></td>
          <td>Literal %</td>
      </tr>
  </tbody>
</table>
<h3 id="space">
  <a class="anchor inpage" href="#space">###</a>Space</h3>
<details open>
    <summary>TEXT</summary><pre
        class="codeblock"
      ><code class="language-" data-lang="">awk -F: &#39;{
    printf &#34;%-10s %s\n&#34;, $1, $(NF-1)
}&#39; /etc/passwd | head -n 3</code><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><p>Outputs</p>
<details open>
    <summary>sh</summary><pre
        class="chroma codeblock"
      ><code class="language-sh" data-lang="sh"
          ><span style="display:flex;"><span>root       /root
</span></span><span style="display:flex;"><span>bin        /bin
</span></span><span style="display:flex;"><span>daemon     /sbin</span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><h3 id="header">
  <a class="anchor inpage" href="#header">###</a>Header</h3>
<details open>
    <summary>TEXT</summary><pre
        class="codeblock"
      ><code class="language-" data-lang="">awk -F: &#39;BEGIN {
    printf &#34;%-10s %s\n&#34;, &#34;User&#34;, &#34;Home&#34;
    printf &#34;%-10s %s\n&#34;, &#34;----&#34;,&#34;----&#34;}
    { printf &#34;%-10s %s\n&#34;, $1, $(NF-1) }
&#39; /etc/passwd | head -n 5</code><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><p>Outputs</p>
<details open>
    <summary>TEXT</summary><pre
        class="codeblock"
      ><code class="language-" data-lang="">User       Home
----       ----
root       /root
bin        /bin
daemon     /sbin</code><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><h2 id="miscellaneous">
  <a class="anchor inpage" href="#miscellaneous">##</a>Miscellaneous</h2>
<h3 id="regex-metacharacters">
  <a class="anchor inpage" href="#regex-metacharacters">###</a>Regex Metacharacters</h3>
<ul>
<li><code>\</code></li>
<li><code>^</code></li>
<li><code>$</code></li>
<li><code>.</code></li>
<li><code>[</code></li>
<li><code>]</code></li>
<li><code>|</code></li>
<li><code>(</code></li>
<li><code>)</code></li>
<li><code>*</code></li>
<li><code>+</code></li>
<li><code>?</code></li>
</ul>
<h3 id="escape-sequences">
  <a class="anchor inpage" href="#escape-sequences">###</a>Escape Sequences</h3>
<table>
  <thead>
      <tr>
          <th>-</th>
          <th>-</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><code>\b</code></td>
          <td>Backspace</td>
      </tr>
      <tr>
          <td><code>\f</code></td>
          <td>Form feed</td>
      </tr>
      <tr>
          <td><code>\n</code></td>
          <td>Newline (line feed)</td>
      </tr>
      <tr>
          <td><code>\r</code></td>
          <td>Carriage return</td>
      </tr>
      <tr>
          <td><code>\t</code></td>
          <td>Horizontal tab</td>
      </tr>
      <tr>
          <td><code>\v</code></td>
          <td>Vertical tab</td>
      </tr>
  </tbody>
</table>
<h3 id="run-script">
  <a class="anchor inpage" href="#run-script">###</a>Run script</h3>
<details open>
    <summary>sh</summary><pre
        class="chroma codeblock"
      ><code class="language-sh" data-lang="sh"
          ><span style="display:flex;"><span>$ cat demo.awk
</span></span><span style="display:flex;"><span><span style="color:#75715e">#!/usr/bin/awk -f</span>
</span></span><span style="display:flex;"><span>BEGIN <span style="color:#f92672">{</span> x <span style="color:#f92672">=</span> <span style="color:#ae81ff">23</span> <span style="color:#f92672">}</span>
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">{</span> x <span style="color:#f92672">+=</span> <span style="color:#ae81ff">2</span> <span style="color:#f92672">}</span>
</span></span><span style="display:flex;"><span>END   <span style="color:#f92672">{</span> print x <span style="color:#f92672">}</span>
</span></span><span style="display:flex;"><span>$ awk -f demo.awk /etc/passwd
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">69</span></span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><h2 id="also-see">
  <a class="anchor inpage" href="#also-see">##</a>Also see</h2>
<ul>
<li>

<em>(www-zeuthen.desy.de)</em></li>
<li>
 <em>(gist.github.com)</em></li>
</ul>
]]></content:encoded></item><item><title>Bash Scripts</title><link>https://hiraethecho.github.io/docs/linux/bash-scripts/</link><pubDate>Tue, 31 Dec 2024 00:00:00 +0000</pubDate><author>wyz2016zxc@outlook.com(Hiraeth)</author><guid>https://hiraethecho.github.io/docs/linux/bash-scripts/</guid><description>编写bash scripts的一些技巧</description><content:encoded><![CDATA[<h1 id="bash-scripts">
  <a class="anchor inpage" href="#bash-scripts">#</a>Bash Scripts</h1>
<h2 id="intro">
  <a class="anchor inpage" href="#intro">##</a>intro</h2>
<h3 id="run">
  <a class="anchor inpage" href="#run">###</a>run</h3>
<p>You can run the script in the following ways:</p>
<p><code>./hello_world.sh</code></p>
<p><code>bash hello_world.sh</code>.</p>
<h3 id="she-bang">
  <a class="anchor inpage" href="#she-bang">###</a>she-bang</h3>
<p>First line of shell Scripts usually is the <code>she-bang</code>:</p>
<details open>
    <summary>TEXT</summary><pre
        class="codeblock"
      ><code class="language-" data-lang="">#!/bin/sh</code><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><p>Means using <code>/bin/sh</code> to run the script.</p>
<p>但是<code>/bin/sh</code>通常是符号链接，在不同机器上实际上是不同的shell，有时会有以外情况。所以建议写成</p>
<details open>
    <summary>TEXT</summary><pre
        class="codeblock"
      ><code class="language-" data-lang="">#!/bin/bash</code><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><h3 id="注释">
  <a class="anchor inpage" href="#%e6%b3%a8%e9%87%8a">###</a>注释</h3>
<p>以 # 开头的行就是注释，会被解释器忽略。</p>
<p>多行注释可以使用以下格式：</p>
<details open>
    <summary>bash</summary><pre
        class="chroma codeblock"
      ><code class="language-bash" data-lang="bash"
          ><span style="display:flex;"><span>:<span style="color:#e6db74">&lt;&lt;EOF
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">注释内容...
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">注释内容...
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">注释内容...
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">EOF</span></span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><p>以上例子中，: 是一个空命令，用于执行后面的 Here 文档， &laquo;&lsquo;EOF&rsquo; 表示开启 Here 文档，COMMENT 是 Here 文档的标识符，在这两个标识符之间的内容都会被视为注释，不会被执行。</p>
<p>EOF 也可以使用其他符号:</p>
<details open>
    <summary>bash</summary><pre
        class="chroma codeblock"
      ><code class="language-bash" data-lang="bash"
          ><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>: <span style="color:#e6db74">&lt;&lt;&#39;COMMENT&#39;
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">这是注释的部分。
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">可以有多行内容。
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">COMMENT</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>:&lt;&lt; <span style="color:#e6db74">&#39;
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">注释内容...
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">注释内容...
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">注释内容...
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">&#39;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>:&lt;&lt;!
</span></span><span style="display:flex;"><span>注释内容...
</span></span><span style="display:flex;"><span>注释内容...
</span></span><span style="display:flex;"><span>注释内容...
</span></span><span style="display:flex;"><span>!</span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><h2 id="variables">
  <a class="anchor inpage" href="#variables">##</a>variables</h2>
<h3 id="define">
  <a class="anchor inpage" href="#define">###</a>define</h3>
<p>We can define a variable by using the syntax <code>variable_name=value</code>. To get the value of the variable, add <code>$</code> before the variable.</p>
<details open>
    <summary>bash</summary><pre
        class="chroma codeblock"
      ><code class="language-bash" data-lang="bash"
          ><span style="display:flex;"><span><span style="color:#75715e">#!/bin/bash
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span><span style="color:#75715e"># A simple variable example</span>
</span></span><span style="display:flex;"><span>greeting<span style="color:#f92672">=</span>Hello
</span></span><span style="display:flex;"><span>name<span style="color:#f92672">=</span>Tux
</span></span><span style="display:flex;"><span>echo $greeting $name</span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><p>注意，变量名和等号之间不能有空格</p>
<p>字符串：</p>
<details open>
    <summary>bash</summary><pre
        class="chroma codeblock"
      ><code class="language-bash" data-lang="bash"
          ><span style="display:flex;"><span>my_string<span style="color:#f92672">=</span><span style="color:#960050;background-color:#1e0010">&#39;</span>Hello, World!my_string<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;Hello, World!&#34;</span></span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><details open>
    <summary>TEXT</summary><pre
        class="codeblock"
      ><code class="language-" data-lang="">RUNOOB=&#34;www.runoob.com&#34;
LD_LIBRARY_PATH=&#34;/bin/&#34;
_var=&#34;123&#34;
var2=&#34;abc&#34;</code><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><details open>
    <summary>bash</summary><pre
        class="chroma codeblock"
      ><code class="language-bash" data-lang="bash"
          ><span style="display:flex;"><span><span style="color:#66d9ef">for</span> file in <span style="color:#ae81ff">\`</span> ls / etc <span style="color:#ae81ff">\`</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">for</span> file in $ <span style="color:#f92672">(</span>ls / etc<span style="color:#f92672">)</span></span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><p>数组：</p>
<details open>
    <summary>TEXT</summary><pre
        class="codeblock"
      ><code class="language-" data-lang="">my_array=(1 2 3 4 5)</code><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><p>只读变量</p>
<details open>
    <summary>bash</summary><pre
        class="chroma codeblock"
      ><code class="language-bash" data-lang="bash"
          ><span style="display:flex;"><span><span style="color:#75715e">#!/bin/bash
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span>myUrl<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;https://www.google.com&#34;</span>
</span></span><span style="display:flex;"><span>readonly myUrl
</span></span><span style="display:flex;"><span>myUrl<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;https://www.runoob.com&#34;</span></span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><p>使用 unset 命令可以删除变量。语法：</p>
<details open>
    <summary>TEXT</summary><pre
        class="codeblock"
      ><code class="language-" data-lang="">unset variable_name</code><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><h3 id="变量类型">
  <a class="anchor inpage" href="#%e5%8f%98%e9%87%8f%e7%b1%bb%e5%9e%8b">###</a>变量类型</h3>
<p><strong>字符串变量：</strong> 在 Shell中，变量通常被视为字符串。</p>
<p>你可以使用单引号 &rsquo; 或双引号 &quot; 来定义字符串，例如：</p>
<details open>
    <summary>TEXT</summary><pre
        class="codeblock"
      ><code class="language-" data-lang="">my_string=&#39;Hello, World!&#39;
my_string=&#34;Hello, World!&#34;</code><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><p>单引号字符串的限制：</p>
<ul>
<li>单引号里的任何字符都会原样输出，单引号字符串中的变量是无效的；</li>
<li>单引号字符串中不能出现单独一个的单引号（对单引号使用转义符后也不行），但可成对出现，作为字符串拼接使用。</li>
</ul>
<p>双引号的优点：</p>
<ul>
<li>双引号里可以有变量</li>
<li>双引号里可以出现转义字符</li>
</ul>
<p>拼接字符串</p>
<details open>
    <summary>bash</summary><pre
        class="chroma codeblock"
      ><code class="language-bash" data-lang="bash"
          ><span style="display:flex;"><span>your<span style="color:#ae81ff">\_</span>name <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;runoob&#34;</span>
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">\#</span> 使用双引号拼接
</span></span><span style="display:flex;"><span>greeting <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;hello, &#34;</span> $your<span style="color:#ae81ff">\_</span>name <span style="color:#e6db74">&#34;!&#34;</span>
</span></span><span style="display:flex;"><span>greeting<span style="color:#ae81ff">\_</span><span style="color:#ae81ff">1</span> <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;hello, </span><span style="color:#e6db74">${</span>your<span style="color:#ae81ff">\_</span>name<span style="color:#e6db74">}</span><span style="color:#e6db74">!&#34;</span>
</span></span><span style="display:flex;"><span>echo $greeting $greeting<span style="color:#ae81ff">\_</span><span style="color:#ae81ff">1</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">\#</span> 使用单引号拼接
</span></span><span style="display:flex;"><span>greeting<span style="color:#ae81ff">\_</span><span style="color:#ae81ff">2</span> <span style="color:#f92672">=</span> <span style="color:#e6db74">&#39;hello, &#39;</span> $your<span style="color:#ae81ff">\_</span>name <span style="color:#e6db74">&#39;!&#39;</span>
</span></span><span style="display:flex;"><span>greeting<span style="color:#ae81ff">\_</span><span style="color:#ae81ff">3</span> <span style="color:#f92672">=</span> <span style="color:#e6db74">&#39;hello, ${your\_name}!&#39;</span>
</span></span><span style="display:flex;"><span>echo $greeting<span style="color:#ae81ff">\_</span><span style="color:#ae81ff">2</span> $greeting<span style="color:#ae81ff">\_</span><span style="color:#ae81ff">3</span></span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><p>输出结果为：</p>
<details open>
    <summary>TEXT</summary><pre
        class="codeblock"
      ><code class="language-" data-lang="">hello, runoob ! hello, runoob !
hello, runoob ! hello, ${your_name} !</code><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><p>获取字符串长度</p>
<details open>
    <summary>bash</summary><pre
        class="chroma codeblock"
      ><code class="language-bash" data-lang="bash"
          ><span style="display:flex;"><span>string <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;abcd&#34;</span>
</span></span><span style="display:flex;"><span>echo <span style="color:#e6db74">${#</span>string<span style="color:#e6db74">}</span> <span style="color:#ae81ff">\#</span> 输出 <span style="color:#ae81ff">4</span></span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><h3 id="数组">
  <a class="anchor inpage" href="#%e6%95%b0%e7%bb%84">###</a>数组</h3>
<p>bash支持一维数组（不支持多维数组），并且没有限定数组的大小。</p>
<p>类似于 C 语言，数组元素的下标由 0 开始编号。获取数组中的元素要利用下标，下标可以是整数或算术表达式，其值应大于或等于 0。</p>
<p>在 Shell 中，用括号来表示数组，数组元素用&quot;空格&quot;符号分割开。定义数组的一般形式为：</p>
<details open>
    <summary>TEXT</summary><pre
        class="codeblock"
      ><code class="language-" data-lang="">数组名=(值1 值2 ... 值n)</code><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><p>例如：</p>
<details open>
    <summary>TEXT</summary><pre
        class="codeblock"
      ><code class="language-" data-lang="">array_name=(value0 value1 value2 value3)</code><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><p>或者</p>
<details open>
    <summary>TEXT</summary><pre
        class="codeblock"
      ><code class="language-" data-lang="">array_name=(
value0
value1
value2
value3
)</code><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><p>还可以单独定义数组的各个分量：</p>
<details open>
    <summary>TEXT</summary><pre
        class="codeblock"
      ><code class="language-" data-lang="">array_name[0]=value0
array_name[1]=value1
array_name[n]=valuen</code><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><p>可以不使用连续的下标，而且下标的范围没有限制。</p>
<p>读取数组元素值的一般格式是：</p>
<details open>
    <summary>TEXT</summary><pre
        class="codeblock"
      ><code class="language-" data-lang="">${数组名[下标]}</code><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><p>例如：</p>
<details open>
    <summary>TEXT</summary><pre
        class="codeblock"
      ><code class="language-" data-lang="">valuen=${array_name[n]}</code><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><p>使用 @ 符号可以获取数组中的所有元素，例如：</p>
<details open>
    <summary>TEXT</summary><pre
        class="codeblock"
      ><code class="language-" data-lang="">echo ${array_name[@]}</code><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><p>获取数组长度的方法与获取字符串长度的方法相同，例如：</p>
<details open>
    <summary>bash</summary><pre
        class="chroma codeblock"
      ><code class="language-bash" data-lang="bash"
          ><span style="display:flex;"><span><span style="color:#ae81ff">\#</span> 取得数组元素的个数
</span></span><span style="display:flex;"><span>length <span style="color:#f92672">=</span> <span style="color:#e6db74">${#</span>array<span style="color:#ae81ff">\_</span>name<span style="color:#ae81ff">\[</span>@<span style="color:#ae81ff">\]</span><span style="color:#e6db74">}</span>
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">\#</span> 或者
</span></span><span style="display:flex;"><span>length <span style="color:#f92672">=</span> <span style="color:#e6db74">${#</span>array<span style="color:#ae81ff">\_</span>name<span style="color:#ae81ff">\[\*\]</span><span style="color:#e6db74">}</span>
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">\#</span> 取得数组单个元素的长度
</span></span><span style="display:flex;"><span>length <span style="color:#f92672">=</span> <span style="color:#e6db74">${#</span>array<span style="color:#ae81ff">\_</span>name<span style="color:#ae81ff">\[</span>n<span style="color:#ae81ff">\]</span><span style="color:#e6db74">}</span></span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><h3 id="运算">
  <a class="anchor inpage" href="#%e8%bf%90%e7%ae%97">###</a>运算</h3>
<p>Arithmetic Expressions:</p>
<p>Below are the operators supported by bash for mathematical calculations:</p>
<table>
  <thead>
      <tr>
          <th>Operator</th>
          <th>Usage</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>+</td>
          <td>addition</td>
      </tr>
      <tr>
          <td>-</td>
          <td>subtraction</td>
      </tr>
      <tr>
          <td>*</td>
          <td>multiplication</td>
      </tr>
      <tr>
          <td>/</td>
          <td>division</td>
      </tr>
      <tr>
          <td>**</td>
          <td>exponentiation</td>
      </tr>
      <tr>
          <td>%</td>
          <td>modulus</td>
      </tr>
  </tbody>
</table>
<p>Numeric Comparison logical operators</p>
<p>Comparison is used to check if statements evaluate to <code>true</code> or <code>false</code>. We can use the below shown operators to compare two statements:</p>
<table>
  <thead>
      <tr>
          <th>Operation</th>
          <th>Syntax</th>
          <th>Explanation</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Equality</td>
          <td>num1 -eq num2</td>
          <td>is num1 equal to num2</td>
      </tr>
      <tr>
          <td>Greater than equal to</td>
          <td>num1 -ge num2</td>
          <td>is num1 greater than equal to num2</td>
      </tr>
      <tr>
          <td>Greater than</td>
          <td>num1 -gt num2</td>
          <td>is num1 greater than num2</td>
      </tr>
      <tr>
          <td>Less than equal to</td>
          <td>num1 -le num2</td>
          <td>is num1 less than equal to num2</td>
      </tr>
      <tr>
          <td>Less than</td>
          <td>num1 -lt num2</td>
          <td>is num1 less than num2</td>
      </tr>
      <tr>
          <td>Not Equal to</td>
          <td>num1 -ne num2</td>
          <td>is num1 not equal to num2</td>
      </tr>
  </tbody>
</table>
<h3 id="参数">
  <a class="anchor inpage" href="#%e5%8f%82%e6%95%b0">###</a>参数</h3>
<table>
  <thead>
      <tr>
          <th>名称</th>
          <th>含义</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>$#</td>
          <td>传给脚本的参数个数</td>
      </tr>
      <tr>
          <td>$0</td>
          <td>脚本本身的名字</td>
      </tr>
      <tr>
          <td>$1</td>
          <td>传递给该shell脚本的第一个参数</td>
      </tr>
      <tr>
          <td>$2</td>
          <td>传递给该shell脚本的第二个参数</td>
      </tr>
      <tr>
          <td>$@</td>
          <td>传给脚本的所有参数的列表</td>
      </tr>
      <tr>
          <td>$*</td>
          <td>以一个单字符串显示所有向脚本传递的参数，与位置变量不同，参数可超过9个</td>
      </tr>
      <tr>
          <td>$$</td>
          <td>脚本运行的当前进程ID号</td>
      </tr>
      <tr>
          <td>$?</td>
          <td>显示最后命令的退出状态，0表示没有错误，其他表示有错误</td>
      </tr>
  </tbody>
</table>
<p>假设执行 <code>./test.sh a b c</code> 这样一个命令，则可以使用下面的参数来获取一些值：</p>
<ul>
<li><code>$0</code><br>
对应 <em>./test.sh</em> 这个值。如果执行的是 <code>./work/test.sh</code> ， 则对应 <em>./work/test.sh</em> 这个值，而不是只返回文件名本身的部分。</li>
<li><code>$1</code><br>
会获取到 a，即 <code>$1</code> 对应传给脚本的第一个参数。</li>
<li><code>$2</code><br>
会获取到 b，即 <code>$2</code> 对应传给脚本的第二个参数。</li>
<li><code>$3</code><br>
会获取到 c，即 <code>$3</code> 对应传给脚本的第三个参数。 <code>$4</code> 、 <code>$5</code> 等参数的含义依此类推。</li>
<li><code>$#</code><br>
会获取到 3，对应传入脚本的参数个数，统计的参数不包括 <code>$0</code> 。</li>
<li><code>$@</code><br>
会获取到 &ldquo;a&rdquo; &ldquo;b&rdquo; &ldquo;c&rdquo;，也就是所有参数的列表，不包括 <code>$0</code> 。</li>
<li><code>$*</code><br>
也会获取到 &ldquo;a&rdquo; &ldquo;b&rdquo; &ldquo;c&rdquo;， 其值和 <code>$@</code> 相同。但 <code>&quot;$*&quot;</code> 和 <code>&quot;$@&quot;</code> 有所不同。<br>
<code>&quot;$*&quot;</code> 把所有参数合并成一个字符串，而 <code>&quot;$@&quot;</code> 会得到一个字符串参数数组。</li>
<li><code>$?</code><br>
可以获取到执行 <code>./test.sh a b c</code> 命令后的返回值。<br>
在执行一个前台命令后，可以立即用 <code>$?</code> 获取到该命令的返回值。<br>
该命令可以是系统自身的命令，可以是 shell 脚本，也可以是自定义的 bash 函数。</li>
</ul>
<p>当执行系统自身的命令时， <code>$?</code> 对应这个命令的返回值。<br>
当执行 shell 脚本时， <code>$?</code> 对应该脚本调用 <code>exit</code> 命令返回的值。如果没有主动调用 <code>exit</code> 命令，默认返回为 0。<br>
当执行自定义的 bash 函数时， <code>$?</code> 对应该函数调用 <code>return</code> 命令返回的值。如果没有主动调用 <code>return</code> 命令，默认返回为 0。</p>
<p>下面举例说明 <code>&quot;$*&quot;</code> 和 <code>&quot;$@&quot;</code> 的差异。假设有一个 <code>testparams.sh</code> 脚本，内容如下：</p>
<details open>
    <summary>bash</summary><pre
        class="chroma codeblock"
      ><code class="language-bash" data-lang="bash"
          ><span style="display:flex;"><span><span style="color:#75715e">#!/bin/bash
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">for</span> arg in <span style="color:#e6db74">&#34;</span>$*<span style="color:#e6db74">&#34;</span>; <span style="color:#66d9ef">do</span>
</span></span><span style="display:flex;"><span>    echo <span style="color:#e6db74">&#34;****:&#34;</span> $arg
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">done</span>
</span></span><span style="display:flex;"><span>echo --------------
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">for</span> arg in <span style="color:#e6db74">&#34;</span>$@<span style="color:#e6db74">&#34;</span>; <span style="color:#66d9ef">do</span>
</span></span><span style="display:flex;"><span>    echo <span style="color:#e6db74">&#34;@@@@:&#34;</span> $arg
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">done</span></span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><p>这个脚本分别遍历 <code>&quot;$*&quot;</code> 和 <code>&quot;$@&quot;</code> 扩展后的内容，并打印出来。</p>
<p>执行 <code>./testparams.sh</code> 脚本，结果如下：</p>
<details open>
    <summary>bash</summary><pre
        class="chroma codeblock"
      ><code class="language-bash" data-lang="bash"
          ><span style="display:flex;"><span>$ ./testparams.sh This is a test
</span></span><span style="display:flex;"><span>****: This is a test
</span></span><span style="display:flex;"><span>--------------
</span></span><span style="display:flex;"><span>@@@@: This
</span></span><span style="display:flex;"><span>@@@@: is
</span></span><span style="display:flex;"><span>@@@@: a
</span></span><span style="display:flex;"><span>@@@@: test</span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><p>可以看到， <code>&quot;$*&quot;</code> 只产生一个字符串，for 循环只遍历一次。<br>
而 <code>&quot;$@&quot;</code> 产生了多个字符串，for 循环遍历多次，是一个字符串参数数组。</p>
<p><strong>注意</strong> ：如果传入的参数多于 9 个，则不能使用 <code>$10</code> 来引用第 10 个参数，而是要用 <code>${10}</code> 来引用。</p>
<p>即，需要用大括号 <code>{}</code> 把大于 9 的数字括起来。<br>
例如， <code>${10}</code> 表示获取第 10 个参数的值，写为 <code>$10</code> 获取不到第 10 个参数的值。<br>
实际上， <code>$10</code> 相当于 <code>${1}0</code> ，也就是先获取 <code>$1</code> 的值，后面再跟上 0。<br>
如果 <code>$1</code> 的值是 &ldquo;first&rdquo;，则 <code>$10</code> 的值是 &ldquo;first0&rdquo;。</p>
<p>在 bash 中，可以使用 <code>$#</code> 来获取传入的命令行或者传入函数的参数个数。<br>
要注意的是， <code>$#</code> 统计的参数个数不包括脚本自身名称或者函数名称。<br>
例如，执行 <code>./a.sh a b</code> ，则 <code>$#</code> 是 2，而不是 3。</p>
<h2 id="pairs">
  <a class="anchor inpage" href="#pairs">##</a>pairs</h2>
<p><code>{}</code>,<code>[]</code>,<code>()</code>,<code>``</code></p>
<h3 id="-花括号">
  <a class="anchor inpage" href="#-%e8%8a%b1%e6%8b%ac%e5%8f%b7">###</a>{} 花括号</h3>
<h4 id="常规用法">
  <a class="anchor inpage" href="#%e5%b8%b8%e8%a7%84%e7%94%a8%e6%b3%95">####</a>常规用法</h4>
<p>大括号拓展。(通配(globbing))将对大括号中的文件名做扩展。在大括号中，不允许有空白，除非这个空白被引用或转义。第一种：对大括号中的以逗号分割的文件列表进行拓展。如 touch {a,b}.txt 结果为a.txt b.txt。第二种：对大括号中以点点（..）分割的顺序文件列表起拓展作用，如：touch {a..d}.txt 结果为a.txt b.txt c.txt d.txt</p>
<details open>
    <summary>TEXT</summary><pre
        class="codeblock"
      ><code class="language-" data-lang=""># ls {ex1,ex2}.sh
ex1.sh  ex2.sh
# ls {ex{1..3},ex4}.sh
ex1.sh  ex2.sh  ex3.sh  ex4.sh
# ls {ex[1-3],ex4}.sh
ex1.sh  ex2.sh  ex3.sh  ex4.sh</code><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><p>代码块，又被称为内部组，这个结构事实上创建了一个匿名函数 。与小括号中的命令不同，大括号内的命令不会新开一个子shell运行，即脚本余下部分仍可使用括号内变量。括号内的命令间用分号隔开，最后一个也必须有分号。{}的第一个命令和左括号之间必须要有一个空格。</p>
<h4 id="几种特殊的替换结构">
  <a class="anchor inpage" href="#%e5%87%a0%e7%a7%8d%e7%89%b9%e6%ae%8a%e7%9a%84%e6%9b%bf%e6%8d%a2%e7%bb%93%e6%9e%84">####</a>几种特殊的替换结构</h4>
<details open>
    <summary>TEXT</summary><pre
        class="codeblock"
      ><code class="language-" data-lang="">${var:-string}
${var:&#43;string}
${var:=string}
${var:?string}</code><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><ol>
<li>
<p><code>${var:-string}</code>和<code>${var:=string}</code>:若变量var为空，则用在命令行中用string来替换<code>${var:-string}</code>，否则变量var不为空时，则用变量var的值来替换<code>${var:-string}</code>；对于<code>${var:=string}</code>的替换规则和<code>${var:-string}</code>是一样的，所不同之处是<code>${var:=string}</code>若var为空时，用string替换<code>${var:=string}</code>的同时，把string赋给变量var： <code>${var:=string}</code>很常用的一种用法是，判断某个变量是否赋值，没有的话则给它赋上一个默认值。</p>
</li>
<li>
<p><code>${var:+string}</code>的替换规则和上面的相反，即只有当var不是空的时候才替换成string，若var为空时则不替换或者说是替换成变量 var的值，即空值。(因为变量var此时为空，所以这两种说法是等价的)</p>
</li>
<li>
<p><code>${var:?string}</code>替换规则为：若变量var不为空，则用变量var的值来替换<code>${var:?string}</code>；若变量var为空，则把string输出到标准错误中，并从脚本中退出。我们可利用此特性来检查是否设置了变量的值。</p>
</li>
</ol>
<p>在上面这五种替换结构中string不一定是常值的，可用另外一个变量的值或是一种命令的输出。</p>
<details open>
    <summary>TEXT</summary><pre
        class="codeblock"
      ><code class="language-" data-lang="">default_name=&#34;Guest&#34;
unset name  # 确保 name 未定义

# 如果 name 为空，则使用 default_name 的值
echo &#34;Hello, ${name:-$default_name}&#34;  # 输出: Hello, Guest</code><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><p><strong>四种模式匹配替换结构</strong></p>
<p>模式匹配记忆方法：</p>
<details open>
    <summary>TEXT</summary><pre
        class="codeblock"
      ><code class="language-" data-lang=""># 是去掉左边(在键盘上#在$之左边)
% 是去掉右边(在键盘上%在$之右边)</code><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><p><code>#</code>和<code>%</code>中的单一符号是最小匹配，两个相同符号是最大匹配。</p>
<details open>
    <summary>TEXT</summary><pre
        class="codeblock"
      ><code class="language-" data-lang="">${var%pattern}
${var%%pattern
${var#pattern}
${var##pattern}</code><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><ul>
<li>第一种模式：<code>${variable%pattern}</code>，这种模式时，shell在variable中查找，看它是否一给的模式pattern结尾，如果是，就从命令行把variable中的内容去掉右边最短的匹配模式</li>
<li>第二种模式： <code>${variable%%pattern}</code>，这种模式时，shell在variable中查找，看它是否一给的模式pattern结尾，如果是，就从命令行把variable中的内容去掉右边最长的匹配模式</li>
<li>第三种模式：<code>${variable#pattern}</code> 这种模式时，shell在variable中查找，看它是否一给的模式pattern开始，如果是，就从命令行把variable中的内容去掉左边最短的匹配模式</li>
<li>第四种模式： <code>${variable##pattern}</code> 这种模式时，shell在variable中查找，看它是否一给的模式pattern结尾，如果是，就从命令行把variable中的内容去掉右边最长的匹配模式</li>
<li>这四种模式中都不会改变variable的值，其中，只有在pattern中使用了*匹配符号时，%和%%，#和##才有区别。结构中的pattern支持通配符，*表示零个或多个任意字符，?表示仅与一个任意字符匹配，\[...\]表示匹配中括号里面的字符，\[!...\]表示不匹配中括号里面的字符。</li>
</ul>
<details open>
    <summary>TEXT</summary><pre
        class="codeblock"
      ><code class="language-" data-lang=""># var=testcase
# echo $var
testcase
# echo ${var%s*e}
testca
# echo $var
testcase
# echo ${var%%s*e}
te
# echo ${var#?e}
stcase
# echo ${var##?e}
stcase
# echo ${var##*e}

# echo ${var##*s}
e
# echo ${var##test}
case</code><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><h4 id="字符串提取和替换">
  <a class="anchor inpage" href="#%e5%ad%97%e7%ac%a6%e4%b8%b2%e6%8f%90%e5%8f%96%e5%92%8c%e6%9b%bf%e6%8d%a2">####</a>字符串提取和替换</h4>
<details open>
    <summary>TEXT</summary><pre
        class="codeblock"
      ><code class="language-" data-lang="">${var:num}
${var:num1:num2}
${var/pattern/pattern}
${var//pattern/pattern}</code><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><ul>
<li>第一种模式：<code>${var:num}</code>，这种模式时，shell在var中提取第num个字符到末尾的所有字符。若num为正数，从左边0处开始；若num为负数，从右边开始提取字串，但必须使用在冒号后面加空格或一个数字或整个num加上括号，如<code>${var: -2}</code>、<code>${var:1-3}</code>或<code>${var:(-2)}</code>。</li>
<li>第二种模式：<code>${var:num1:num2}</code>，num1是位置，num2是长度。表示从$var字符串的第$num1个位置开始提取长度为$num2的子串。不能为负数。</li>
<li>第三种模式：<code>${var/pattern/pattern}</code>表示将var字符串的第一个匹配的pattern替换为另一个pattern。</li>
<li>第四种模式：<code>${var//pattern/pattern}</code>表示将var字符串中的所有能匹配的pattern替换为另一个pattern。</li>
</ul>
<details open>
    <summary>TEXT</summary><pre
        class="codeblock"
      ><code class="language-" data-lang="">[root@centos ~]# var=/home/centos
[root@centos ~]# echo $var
/home/centos
[root@centos ~]# echo ${var:5}
/centos
[root@centos ~]# echo ${var: -6}
centos
[root@centos ~]# echo ${var:(-6)}
centos
[root@centos ~]# echo ${var:1:4}
home
[root@centos ~]# echo ${var/o/h}
/hhme/centos
[root@centos ~]# echo ${var//o/h}
/hhme/cenths</code><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><ul>
<li>
<p>${a} 变量a的值, 在不引起歧义的情况下可以省略大括号。</p>
</li>
<li>
<p>$(cmd) 命令替换，和`cmd`效果相同，结果为shell命令cmd的输，过某些Shell版本不支持$()形式的命令替换, 如tcsh。</p>
</li>
<li>
<p>$((expression)) 和`exprexpression`效果相同, 计算数学表达式exp的数值, 其中exp只要符合C语言的运算规则即可, 甚至三目运算符和逻辑表达式都可以计算。</p>
</li>
<li>
<p>单小括号，(cmd1;cmd2;cmd3) 新开一个子shell顺序执行命令cmd1,cmd2,cmd3, 各命令之间用分号隔开, 最后一个命令后可以没有分号。</p>
</li>
<li>
<p>单大括号，{ cmd1;cmd2;cmd3;} 在当前shell顺序执行命令cmd1,cmd2,cmd3, 各命令之间用分号隔开, 最后一个命令后必须有分号, 第一条命令和左括号之间必须用空格隔开。
对 {} 和 () 而言, 括号中的重定向符只影响该条命令， 而括号外的重定向符影响到括号中的所有命令。</p>
</li>
</ul>
<h3 id="heading">
  <a class="anchor inpage" href="#heading">###</a><code>[]</code></h3>
<details open>
    <summary>bash</summary><pre
        class="chroma codeblock"
      ><code class="language-bash" data-lang="bash"
          ><span style="display:flex;"><span>type <span style="color:#f92672">[</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">[</span> is a shell builtin</span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><p>This means that &lsquo;[&rsquo; is actually a program, just like ls and other programs, so it must be surrounded by spaces.</p>
<ul>
<li>bash 的内部命令，[和test是等同的。如果我们不用绝对路径指明，通常我们用的都是bash自带的命令。if/test结构中的左中括号是调用test的命令标识，右中括号是关闭条件判断的。这个命令把它的参数作为比较表达式或者作为文件测试，并且根据比较的结果来返回一个退出状态码。if/test结构中并不是必须右中括号，但是新版的Bash中要求必须这样。</li>
<li>Test和[]中可用的比较运算符只有==和!=，两者都是用于字符串比较的，不可用于整数比较，整数比较只能使用-eq，-gt这种形式。无论是字符串比较还是整数比较都不支持大于号小于号。如果实在想用，对于字符串比较可以使用转义形式，如果比较&quot;ab&quot;和&quot;bc&quot;：\[ ab \\< bc \]，结果为真，也就是返回状态为0。\[ \]中的逻辑与和逻辑或使用-a 和-o 表示。</li>
<li>字符范围。用作正则表达式的一部分，描述一个匹配的字符范围。作为test用途的中括号内不能使用正则。</li>
<li>在一个array 结构的上下文中，中括号用来引用数组中每个元素的编号。</li>
</ul>
<h3 id="heading-1">
  <a class="anchor inpage" href="#heading-1">###</a><code>[[]]</code></h3>
<ul>
<li>\[\[是 bash 程序语言的关键字。并不是一个命令，\[\[ \]] 结构比\[ \]结构更加通用。在\[\[和\]]之间所有的字符都不会发生文件名扩展或者单词分割，但是会发生参数扩展和命令替换。</li>
<li>支持字符串的模式匹配，使用=~操作符时甚至支持shell的正则表达式。字符串比较时可以把右边的作为一个模式，而不仅仅是一个字符串，比如\[\[ hello == hell? \]]，结果为真。\[\[ \]] 中匹配字符串或通配符，不需要引号。</li>
<li>使用\[\[... \]]条件判断结构，而不是\[... \]，能够防止脚本中的许多逻辑错误。比如，&amp;&amp;、||、&lt;和&gt; 操作符能够正常存在于\[\[ \]]条件判断结构中，但是如果出现在\[ \]结构中的话，会报错。比如可以直接使用if \[\[ $a!= 1 && $a!= 2 \]], 如果不适用双括号, 则为if \[ $a -ne 1\] &amp;&amp; \[ $a!= 2 \]或者if \[ $a -ne 1 -a $a!= 2 \]。</li>
<li>bash把双中括号中的表达式看作一个单独的元素，并返回一个退出状态码。</li>
</ul>
<details open>
    <summary>bash</summary><pre
        class="chroma codeblock"
      ><code class="language-bash" data-lang="bash"
          ><span style="display:flex;"><span><span style="color:#66d9ef">if</span> <span style="color:#f92672">(</span>$i&lt;5<span style="color:#f92672">)</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">if</span> <span style="color:#f92672">[</span> $i -lt <span style="color:#ae81ff">5</span> <span style="color:#f92672">]</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">if</span> <span style="color:#f92672">[</span> $a -ne <span style="color:#ae81ff">1</span> -a $a !<span style="color:#f92672">=</span> <span style="color:#ae81ff">2</span> <span style="color:#f92672">]</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">if</span> <span style="color:#f92672">[</span> $a -ne 1<span style="color:#f92672">]</span> <span style="color:#f92672">&amp;&amp;</span> <span style="color:#f92672">[</span> $a !<span style="color:#f92672">=</span> <span style="color:#ae81ff">2</span> <span style="color:#f92672">]</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">if</span> <span style="color:#f92672">[[</span> $a !<span style="color:#f92672">=</span> <span style="color:#ae81ff">1</span> <span style="color:#f92672">&amp;&amp;</span> $a !<span style="color:#f92672">=</span> <span style="color:#ae81ff">2</span> <span style="color:#f92672">]]</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">for</span> i in <span style="color:#66d9ef">$(</span>seq <span style="color:#ae81ff">0</span> 4<span style="color:#66d9ef">)</span>;<span style="color:#66d9ef">do</span> echo $i;<span style="color:#66d9ef">done</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">for</span> i in <span style="color:#ae81ff">\`</span>seq <span style="color:#ae81ff">0</span> 4<span style="color:#ae81ff">\`</span>;<span style="color:#66d9ef">do</span> echo $i;<span style="color:#66d9ef">done</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">for</span> <span style="color:#f92672">((</span>i<span style="color:#f92672">=</span>0;i&lt;5;i++<span style="color:#f92672">))</span>;<span style="color:#66d9ef">do</span> echo $i;<span style="color:#66d9ef">done</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">for</span> i in <span style="color:#f92672">{</span>0..4<span style="color:#f92672">}</span>;<span style="color:#66d9ef">do</span> echo $i;<span style="color:#66d9ef">done</span></span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><h3 id="-和-">
  <a class="anchor inpage" href="#-%e5%92%8c-">###</a><code>[]</code> 和 <code>[[]]</code></h3>
<p>在 <strong>Bash</strong> 脚本中，<code>[ ]</code>（<code>test</code> 命令）和 <code>[[ ]]</code>（关键字）都用于条件判断，但它们在功能、性能和安全性上有显著区别。以下是详细对比：</p>
<h4 id="基本定义">
  <a class="anchor inpage" href="#%e5%9f%ba%e6%9c%ac%e5%ae%9a%e4%b9%89">####</a>基本定义</h4>
<table>
  <thead>
      <tr>
          <th>语法</th>
          <th>类型</th>
          <th>说明</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><code>[ ]</code></td>
          <td><strong>内置命令</strong></td>
          <td>等价于 <code>test</code> 命令，需严格遵循参数规则（如空格和引号）。</td>
      </tr>
      <tr>
          <td><code>[[ ]]</code></td>
          <td><strong>Shell 关键字</strong></td>
          <td>Bash/ksh/zsh 的扩展语法，更灵活，支持额外功能（如模式匹配、逻辑组合）。</td>
      </tr>
  </tbody>
</table>
<h4 id="核心区别">
  <a class="anchor inpage" href="#%e6%a0%b8%e5%bf%83%e5%8c%ba%e5%88%ab">####</a>核心区别</h4>
<p><strong>(1) 字符串比较</strong></p>
<ul>
<li>
<p><strong><code>[ ]</code></strong>：</p>
<ul>
<li>使用 <code>=</code> 和 <code>!=</code> 时，<strong>必须加引号</strong>，否则可能因空格或特殊字符报错。</li>
<li>示例：
<details open>
    <summary>bash</summary><pre
        class="chroma codeblock"
      ><code class="language-bash" data-lang="bash"
          ><span style="display:flex;"><span><span style="color:#f92672">[</span> <span style="color:#e6db74">&#34;</span>$var<span style="color:#e6db74">&#34;</span> <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;hello&#34;</span> <span style="color:#f92672">]</span>  <span style="color:#75715e"># 正确</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">[</span> $var <span style="color:#f92672">=</span> hello <span style="color:#f92672">]</span>      <span style="color:#75715e"># 若 $var 含空格，会报错</span></span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script></li>
</ul>
</li>
<li>
<p><strong><code>[[ ]]</code></strong>：</p>
<ul>
<li>自动处理变量中的空格，无需引号（但仍建议加引号以防未定义变量）。</li>
<li>支持 <code>==</code> 和 <code>!=</code> 的<strong>通配符匹配</strong>（模式匹配）。</li>
<li>示例：
<details open>
    <summary>bash</summary><pre
        class="chroma codeblock"
      ><code class="language-bash" data-lang="bash"
          ><span style="display:flex;"><span><span style="color:#f92672">[[</span> $var <span style="color:#f92672">==</span> <span style="color:#e6db74">&#34;hello&#34;</span> <span style="color:#f92672">]]</span>    <span style="color:#75715e"># 正确，即使 $var 含空格</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">[[</span> $var <span style="color:#f92672">==</span> h* <span style="color:#f92672">]]</span>         <span style="color:#75715e"># 支持通配符匹配（如 &#34;hello&#34; 或 &#34;hi&#34;）</span></span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script></li>
</ul>
</li>
</ul>
<p><strong>(2) 数值比较</strong></p>
<ul>
<li>
<p><strong><code>[ ]</code></strong>：</p>
<ul>
<li>必须用 <code>-eq</code>、<code>-lt</code> 等运算符：
<details open>
    <summary>bash</summary><pre
        class="chroma codeblock"
      ><code class="language-bash" data-lang="bash"
          ><span style="display:flex;"><span><span style="color:#f92672">[</span> <span style="color:#e6db74">&#34;</span>$num<span style="color:#e6db74">&#34;</span> -lt <span style="color:#ae81ff">5</span> <span style="color:#f92672">]</span>  <span style="color:#75715e"># 数值比较</span></span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script></li>
</ul>
</li>
<li>
<p><strong><code>[[ ]]</code></strong>：</p>
<ul>
<li>仍建议用 <code>-eq</code>、<code>-lt</code>，但支持 <code>&gt;</code> 和 <code>&lt;</code>（需转义或双括号）：
<details open>
    <summary>bash</summary><pre
        class="chroma codeblock"
      ><code class="language-bash" data-lang="bash"
          ><span style="display:flex;"><span><span style="color:#f92672">[[</span> $num -lt <span style="color:#ae81ff">5</span> <span style="color:#f92672">]]</span>    <span style="color:#75715e"># 标准写法</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">[[</span> $num &lt; <span style="color:#ae81ff">10</span> <span style="color:#f92672">]]</span>     <span style="color:#75715e"># 字符串比较（字典序）！</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">((</span> num &lt; <span style="color:#ae81ff">10</span> <span style="color:#f92672">))</span>      <span style="color:#75715e"># 数值比较的正确写法</span></span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script></li>
</ul>
</li>
</ul>
<p><strong>(3) 逻辑运算符</strong></p>
<ul>
<li>
<p><strong><code>[ ]</code></strong>：</p>
<ul>
<li>用 <code>-a</code>（AND）、<code>-o</code>（OR），需严格分隔：
<details open>
    <summary>bash</summary><pre
        class="chroma codeblock"
      ><code class="language-bash" data-lang="bash"
          ><span style="display:flex;"><span><span style="color:#f92672">[</span> <span style="color:#e6db74">&#34;</span>$a<span style="color:#e6db74">&#34;</span> -gt <span style="color:#ae81ff">1</span> -a <span style="color:#e6db74">&#34;</span>$a<span style="color:#e6db74">&#34;</span> -lt <span style="color:#ae81ff">10</span> <span style="color:#f92672">]</span></span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script></li>
</ul>
</li>
<li>
<p><strong><code>[[ ]]</code></strong>：</p>
<ul>
<li>用 <code>&amp;&amp;</code> 和 <code>||</code>，更直观：
<details open>
    <summary>bash</summary><pre
        class="chroma codeblock"
      ><code class="language-bash" data-lang="bash"
          ><span style="display:flex;"><span><span style="color:#f92672">[[</span> $a -gt <span style="color:#ae81ff">1</span> <span style="color:#f92672">&amp;&amp;</span> $a -lt <span style="color:#ae81ff">10</span> <span style="color:#f92672">]]</span></span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script></li>
</ul>
</li>
</ul>
<p><strong>(4) 文件测试</strong></p>
<ul>
<li><strong><code>[ ]</code></strong> 和 <code>[[ ]]</code> 均支持，但 <code>[[ ]]</code> 更安全（如未定义变量不会报错）：
<details open>
    <summary>bash</summary><pre
        class="chroma codeblock"
      ><code class="language-bash" data-lang="bash"
          ><span style="display:flex;"><span><span style="color:#f92672">[</span> -f <span style="color:#e6db74">&#34;</span>$file<span style="color:#e6db74">&#34;</span> <span style="color:#f92672">]</span>      <span style="color:#75715e"># 检查文件是否存在</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">[[</span> -f $file <span style="color:#f92672">]]</span>      <span style="color:#75715e"># 更健壮（即使 $file 未定义也不会语法错误）</span></span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script></li>
</ul>
<p><strong>(5) 正则匹配（仅 <code>[[ ]]</code>）</strong></p>
<details open>
    <summary>bash</summary><pre
        class="chroma codeblock"
      ><code class="language-bash" data-lang="bash"
          ><span style="display:flex;"><span><span style="color:#f92672">[[</span> <span style="color:#e6db74">&#34;hello&#34;</span> <span style="color:#f92672">=</span>~ ^h <span style="color:#f92672">]]</span>   <span style="color:#75715e"># 正则匹配（返回 true）</span></span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><h4 id="性能与安全性">
  <a class="anchor inpage" href="#%e6%80%a7%e8%83%bd%e4%b8%8e%e5%ae%89%e5%85%a8%e6%80%a7">####</a>性能与安全性</h4>
<table>
  <thead>
      <tr>
          <th>特性</th>
          <th><code>[ ]</code></th>
          <th><code>[[ ]]</code></th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><strong>执行速度</strong></td>
          <td>较慢（外部命令或内置命令）</td>
          <td>更快（Bash 关键字）</td>
      </tr>
      <tr>
          <td><strong>安全性</strong></td>
          <td>变量未加引号易报错</td>
          <td>自动处理空格，更健壮</td>
      </tr>
      <tr>
          <td><strong>兼容性</strong></td>
          <td>所有 Shell（sh、dash 等）</td>
          <td>仅 Bash/ksh/zsh</td>
      </tr>
  </tbody>
</table>
<h4 id="何时使用">
  <a class="anchor inpage" href="#%e4%bd%95%e6%97%b6%e4%bd%bf%e7%94%a8">####</a>何时使用？</h4>
<ul>
<li><strong>用 <code>[[ ]]</code></strong>：
<ul>
<li>需要模式匹配、正则表达式、逻辑组合时。</li>
<li>脚本已明确使用 Bash（<code>#!/bin/bash</code>）。</li>
</ul>
</li>
<li><strong>用 <code>[ ]</code></strong>：
<ul>
<li>需兼容 POSIX Shell（如 <code>/bin/sh</code>）。</li>
<li>简单的文件或字符串测试（但务必加引号）。</li>
</ul>
</li>
</ul>
<h4 id="经典示例">
  <a class="anchor inpage" href="#%e7%bb%8f%e5%85%b8%e7%a4%ba%e4%be%8b">####</a>经典示例</h4>
<p><strong>(1) 字符串比较</strong></p>
<details open>
    <summary>bash</summary><pre
        class="chroma codeblock"
      ><code class="language-bash" data-lang="bash"
          ><span style="display:flex;"><span><span style="color:#75715e"># [ ] 必须加引号</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">[</span> <span style="color:#e6db74">&#34;</span>$name<span style="color:#e6db74">&#34;</span> <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;Alice&#34;</span> <span style="color:#f92672">]</span> <span style="color:#f92672">&amp;&amp;</span> echo <span style="color:#e6db74">&#34;Hello Alice&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># [[ ]] 更灵活</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">[[</span> $name <span style="color:#f92672">==</span> A* <span style="color:#f92672">]]</span> <span style="color:#f92672">&amp;&amp;</span> echo <span style="color:#e6db74">&#34;Name starts with A&#34;</span></span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><p><strong>(2) 文件检查</strong></p>
<details open>
    <summary>bash</summary><pre
        class="chroma codeblock"
      ><code class="language-bash" data-lang="bash"
          ><span style="display:flex;"><span><span style="color:#75715e"># [ ] 和 [[ ]] 均可，但后者更安全</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">[</span> -f <span style="color:#e6db74">&#34;/path/</span>$file<span style="color:#e6db74">&#34;</span> <span style="color:#f92672">]</span> <span style="color:#f92672">&amp;&amp;</span> echo <span style="color:#e6db74">&#34;File exists&#34;</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">[[</span> -f /path/$file <span style="color:#f92672">]]</span> <span style="color:#f92672">&amp;&amp;</span> echo <span style="color:#e6db74">&#34;File exists&#34;</span></span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><p><strong>(3) 逻辑组合</strong></p>
<details open>
    <summary>bash</summary><pre
        class="chroma codeblock"
      ><code class="language-bash" data-lang="bash"
          ><span style="display:flex;"><span><span style="color:#75715e"># [ ] 用 -a/-o</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">[</span> <span style="color:#e6db74">&#34;</span>$age<span style="color:#e6db74">&#34;</span> -gt <span style="color:#ae81ff">18</span> -a <span style="color:#e6db74">&#34;</span>$age<span style="color:#e6db74">&#34;</span> -lt <span style="color:#ae81ff">60</span> <span style="color:#f92672">]</span> <span style="color:#f92672">&amp;&amp;</span> echo <span style="color:#e6db74">&#34;Valid age&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># [[ ]] 用 &amp;&amp;/||</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">[[</span> $age -gt <span style="color:#ae81ff">18</span> <span style="color:#f92672">&amp;&amp;</span> $age -lt <span style="color:#ae81ff">60</span> <span style="color:#f92672">]]</span> <span style="color:#f92672">&amp;&amp;</span> echo <span style="color:#e6db74">&#34;Valid age&#34;</span></span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><h4 id="总结">
  <a class="anchor inpage" href="#%e6%80%bb%e7%bb%93">####</a>总结</h4>
<table>
  <thead>
      <tr>
          <th><strong>需求</strong></th>
          <th><strong><code>[ ]</code></strong></th>
          <th><strong><code>[[ ]]</code></strong></th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>字符串比较</td>
          <td>需严格加引号</td>
          <td>自动处理空格，支持通配符</td>
      </tr>
      <tr>
          <td>数值比较</td>
          <td>用 <code>-eq</code>、<code>-lt</code></td>
          <td>同 <code>[ ]</code>，但可用 <code>(( ))</code> 替代</td>
      </tr>
      <tr>
          <td>逻辑运算符</td>
          <td><code>-a</code>、<code>-o</code></td>
          <td><code>&amp;&amp;</code>、<code>||</code></td>
      </tr>
      <tr>
          <td>正则匹配</td>
          <td>❌</td>
          <td>✅（<code>=~</code>）</td>
      </tr>
      <tr>
          <td>性能</td>
          <td>较慢</td>
          <td>更快</td>
      </tr>
  </tbody>
</table>
<ul>
<li><strong>优先用 <code>[[ ]]</code></strong>（Bash 脚本中更安全、灵活）。</li>
<li><strong>只有需要兼容 POSIX 时用 <code>[ ]</code></strong>（如 <code>/bin/sh</code> 脚本）。</li>
</ul>
<h3 id="heading-2">
  <a class="anchor inpage" href="#heading-2">###</a><code>()</code></h3>
<ul>
<li><strong>命令组</strong> 。括号中的命令将会新开一个子shell顺序执行，所以括号中的变量不能够被脚本余下的部分使用。括号中多个命令之间用分号隔开，最后一个命令可以没有分号，各命令和括号之间不必有空格。</li>
<li><strong>命令替换</strong> 。等同于<code>cmd</code>，shell扫描一遍命令行，发现了<code>$(cmd)</code>结构，便将<code>$(cmd)</code>中的<code>cmd</code>执行一次，得到其标准输出，再将此输出放到原来命令。有些shell不支持，如tcsh。</li>
<li><strong>用于初始化数组</strong> 。如：<code>array=(a b c d)</code></li>
</ul>
<h3 id="heading-3">
  <a class="anchor inpage" href="#heading-3">###</a><code>(())</code></h3>
<ul>
<li>整数扩展。这种扩展计算是整数型的计算，不支持浮点型。((exp))结构扩展并计算一个算术表达式的值，如果表达式的结果为0，那么返回的退出状态码为1，或者 是&quot;假&quot;，而一个非零值的表达式所返回的退出状态码将为0，或者是&quot;true&quot;。若是逻辑判断，表达式exp为真则为1,假则为0。</li>
<li>只要括号中的运算符、表达式符合C语言运算规则，都可用在$((exp))中，甚至是三目运算符。作不同进位(如二进制、八进制、十六进制)运算时，输出结果全都自动转化成了十进制。如：echo $((16#5f)) 结果为95 (16进位转十进制)</li>
<li>单纯用 (( )) 也可重定义变量值，比如 a=5; ((a++)) 可将 $a 重定义为6</li>
<li>常用于算术运算比较，双括号中的变量可以不使用<code>$</code>符号前缀。括号内支持多个表达式用逗号分开。 只要括号中的表达式符合C语言运算规则,比如可以直接使用<code>for((i=0;i&lt;5;i++))</code>, 如果不使用双括号, 则为<code>for i in $(seq 0 4)</code>或者<code>for i in {0..4}</code>。再如可以直接使用<code>if (($i&lt;5))</code>, 如果不使用双括号, 则为<code>if \[ $i -lt 5 \]</code>。</li>
</ul>
<details open>
    <summary>bash</summary><pre
        class="chroma codeblock"
      ><code class="language-bash" data-lang="bash"
          ><span style="display:flex;"><span>var<span style="color:#f92672">=</span><span style="color:#66d9ef">$((</span>expression<span style="color:#66d9ef">))</span></span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><h3 id="-back-ticks">
  <a class="anchor inpage" href="#-back-ticks">###</a><code>``</code> back ticks</h3>
<p>var= commands</p>
<p><strong>Example</strong>: Suppose we want to get the output of a list of mountpoints with <code>tmpfs</code> in their name. We can craft a statement like this: <code>df -h | grep tmpfs</code>.</p>
<p>To include it in the bash script, we can enclose it in back ticks.</p>
<details open>
    <summary>bash</summary><pre
        class="chroma codeblock"
      ><code class="language-bash" data-lang="bash"
          ><span style="display:flex;"><span><span style="color:#75715e">#!/bin/bash
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span>var<span style="color:#f92672">=</span><span style="color:#ae81ff">\`</span>df -h | grep tmpfs<span style="color:#ae81ff">\`</span>
</span></span><span style="display:flex;"><span>echo $var</span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><h3 id="heading-4">
  <a class="anchor inpage" href="#heading-4">###</a><code>&quot;&quot;</code></h3>
<details open>
    <summary>bash</summary><pre
        class="chroma codeblock"
      ><code class="language-bash" data-lang="bash"
          ><span style="display:flex;"><span>repo<span style="color:#f92672">=</span>~<span style="color:#e6db74">&#34;/projects/repo1&#34;</span>  <span style="color:#75715e"># 或直接写 ~/projects/repo1（不加引号）</span>
</span></span><span style="display:flex;"><span>cd <span style="color:#e6db74">&#34;</span>$repo<span style="color:#e6db74">&#34;</span>               <span style="color:#75715e"># 此时 $repo 已是展开后的绝对路径</span></span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><details open>
    <summary>bash</summary><pre
        class="chroma codeblock"
      ><code class="language-bash" data-lang="bash"
          ><span style="display:flex;"><span><span style="color:#75715e">#!/bin/bash
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># 显式展开家目录</span>
</span></span><span style="display:flex;"><span>HOME_DIR<span style="color:#f92672">=</span><span style="color:#66d9ef">$(</span>eval echo <span style="color:#e6db74">&#34;~&#34;</span><span style="color:#66d9ef">)</span>  <span style="color:#75715e"># 或直接写 HOME_DIR=&#34;$HOME&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>repos<span style="color:#f92672">=(</span>
</span></span><span style="display:flex;"><span>    <span style="color:#e6db74">&#34;</span>$HOME_DIR<span style="color:#e6db74">/projects/repo1&#34;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#e6db74">&#34;</span>$HOME_DIR<span style="color:#e6db74">/work/repo2&#34;</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">)</span></span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><h3 id="-和--1">
  <a class="anchor inpage" href="#-%e5%92%8c--1">###</a><code>&quot;&quot;</code> 和 <code>''</code></h3>
<p>在 <strong>Bash</strong> 脚本中，双引号 <code>&quot;&quot;</code> 和单引号 <code>''</code> 都用于定义字符串，但它们在 <strong>变量扩展</strong>、<strong>命令替换</strong> 和 <strong>特殊字符处理</strong> 上有本质区别。以下是详细对比：</p>
<table>
  <thead>
      <tr>
          <th>特性</th>
          <th>双引号 <code>&quot;&quot;</code></th>
          <th>单引号 <code>''</code></th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><strong>变量扩展</strong></td>
          <td>✅（如 <code>&quot;$var&quot;</code> 会展开）</td>
          <td>❌（如 <code>'$var'</code> 原样输出）</td>
      </tr>
      <tr>
          <td><strong>命令替换</strong></td>
          <td>✅（如 <code>&quot;$(date)&quot;</code> 会执行）</td>
          <td>❌（如 <code>'$(date)'</code> 原样输出）</td>
      </tr>
      <tr>
          <td><strong>转义字符</strong></td>
          <td>仅 <code>\</code>, <code>$</code>, <code>`</code>, <code>&quot;</code> 生效</td>
          <td>所有字符均按字面处理（无转义）</td>
      </tr>
      <tr>
          <td><strong>用途</strong></td>
          <td>需保留变量或命令结果时使用</td>
          <td>需完全按字面输出时使用</td>
      </tr>
  </tbody>
</table>
<details open>
    <summary>bash</summary><pre
        class="chroma codeblock"
      ><code class="language-bash" data-lang="bash"
          ><span style="display:flex;"><span>name<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;Alice&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>echo <span style="color:#e6db74">&#34;Hello, </span>$name<span style="color:#e6db74">&#34;</span>   <span style="color:#75715e"># 输出: Hello, Alice</span>
</span></span><span style="display:flex;"><span>echo <span style="color:#e6db74">&#39;Hello, $name&#39;</span>   <span style="color:#75715e"># 输出: Hello, $name</span></span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><details open>
    <summary>bash</summary><pre
        class="chroma codeblock"
      ><code class="language-bash" data-lang="bash"
          ><span style="display:flex;"><span>echo <span style="color:#e6db74">&#34;Today is </span><span style="color:#66d9ef">$(</span>date<span style="color:#66d9ef">)</span><span style="color:#e6db74">&#34;</span>  <span style="color:#75715e"># 输出: Today is Mon Jul 1 12:00:00 UTC 2024</span>
</span></span><span style="display:flex;"><span>echo <span style="color:#e6db74">&#39;Today is $(date)&#39;</span>  <span style="color:#75715e"># 输出: Today is $(date)</span></span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><details open>
    <summary>bash</summary><pre
        class="chroma codeblock"
      ><code class="language-bash" data-lang="bash"
          ><span style="display:flex;"><span>echo <span style="color:#e6db74">&#34;Path is \$HOME&#34;</span>    <span style="color:#75715e"># 输出: Path is $HOME（\$ 被转义）</span>
</span></span><span style="display:flex;"><span>echo <span style="color:#e6db74">&#39;Path is \$HOME&#39;</span>    <span style="color:#75715e"># 输出: Path is \$HOME（完全字面）</span></span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><details open>
    <summary>bash</summary><pre
        class="chroma codeblock"
      ><code class="language-bash" data-lang="bash"
          ><span style="display:flex;"><span>echo <span style="color:#e6db74">&#34;She said: &#39;Hello!&#39;&#34;</span>   <span style="color:#75715e"># 输出: She said: &#39;Hello!&#39;</span>
</span></span><span style="display:flex;"><span>echo <span style="color:#e6db74">&#39;He said: &#34;Hi!&#34;&#39;</span>       <span style="color:#75715e"># 输出: He said: &#34;Hi!&#34;</span></span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><ul>
<li>
<p>需要<strong>变量或命令替换</strong>时：</p>
<details open>
    <summary>bash</summary><pre
        class="chroma codeblock"
      ><code class="language-bash" data-lang="bash"
          ><span style="display:flex;"><span>echo <span style="color:#e6db74">&#34;Current user: </span>$USER<span style="color:#e6db74">, time: </span><span style="color:#66d9ef">$(</span>date<span style="color:#66d9ef">)</span><span style="color:#e6db74">&#34;</span></span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script></li>
<li>
<p>字符串中包含<strong>空格或特殊字符</strong>（需部分转义）：</p>
<details open>
    <summary>bash</summary><pre
        class="chroma codeblock"
      ><code class="language-bash" data-lang="bash"
          ><span style="display:flex;"><span>echo <span style="color:#e6db74">&#34;Use \&#34;quotes\&#34; inside.&#34;</span></span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script></li>
<li>
<p>需<strong>完全按字面输出</strong>（如正则表达式、SQL语句）：</p>
<details open>
    <summary>bash</summary><pre
        class="chroma codeblock"
      ><code class="language-bash" data-lang="bash"
          ><span style="display:flex;"><span>grep -E <span style="color:#e6db74">&#39;^[A-Z]&#39;</span> file.txt  <span style="color:#75715e"># 正则表达式</span>
</span></span><span style="display:flex;"><span>sql<span style="color:#f92672">=</span><span style="color:#e6db74">&#39;SELECT * FROM users;&#39;</span> <span style="color:#75715e"># SQL语句</span></span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script></li>
<li>
<p>避免<strong>特殊字符被解析</strong>：</p>
<details open>
    <summary>bash</summary><pre
        class="chroma codeblock"
      ><code class="language-bash" data-lang="bash"
          ><span style="display:flex;"><span>echo <span style="color:#e6db74">&#39;$PATH and $(date)&#39;</span>  <span style="color:#75715e"># 输出: $PATH and $(date)</span></span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script></li>
</ul>
<p><strong>特殊情况处理</strong></p>
<details open>
    <summary>bash</summary><pre
        class="chroma codeblock"
      ><code class="language-bash" data-lang="bash"
          ><span style="display:flex;"><span>alias rm<span style="color:#f92672">=</span><span style="color:#e6db74">&#39;rm -i&#39;</span>          <span style="color:#75715e"># 单引号内定义别名（避免变量提前展开）</span>
</span></span><span style="display:flex;"><span>echo <span style="color:#e6db74">&#34;It&#39;s a sunny day.&#34;</span>  <span style="color:#75715e"># 双引号内嵌套单引号（无需转义）</span></span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><details open>
    <summary>bash</summary><pre
        class="chroma codeblock"
      ><code class="language-bash" data-lang="bash"
          ><span style="display:flex;"><span>echo <span style="color:#e6db74">&#34;Line 1\nLine 2&#34;</span>     <span style="color:#75715e"># 输出: Line 1\nLine 2（\n 未被转义为换行）</span>
</span></span><span style="display:flex;"><span>echo -e <span style="color:#e6db74">&#34;Line 1\nLine 2&#34;</span>  <span style="color:#75715e"># 输出两行（-e 启用转义）</span>
</span></span><span style="display:flex;"><span>echo <span style="color:#e6db74">&#39;Line 1\nLine 2&#39;</span>     <span style="color:#75715e"># 输出: Line 1\nLine 2（完全字面）</span></span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><ul>
<li><strong>单引号稍快</strong>：因为无需解析变量或命令替换。</li>
<li>实际脚本中差异可忽略，优先考虑功能需求。</li>
</ul>
<ol>
<li><strong>默认用双引号</strong>：<br>
保护变量中的空格（如 <code>&quot;$file&quot;</code>），避免路径或文件名错误拆分。
<details open>
    <summary>bash</summary><pre
        class="chroma codeblock"
      ><code class="language-bash" data-lang="bash"
          ><span style="display:flex;"><span>cp <span style="color:#e6db74">&#34;</span>$file<span style="color:#e6db74">&#34;</span> <span style="color:#e6db74">&#34;/backup/</span>$file<span style="color:#e6db74">&#34;</span>  <span style="color:#75715e"># 正确处理含空格的文件名</span></span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script></li>
<li><strong>需要纯文本时用单引号</strong>：<br>
如正则表达式、代码生成、避免意外展开。
<details open>
    <summary>bash</summary><pre
        class="chroma codeblock"
      ><code class="language-bash" data-lang="bash"
          ><span style="display:flex;"><span>sed -e <span style="color:#e6db74">&#39;s/foo/bar/g&#39;</span> file.txt</span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script></li>
</ol>
<h2 id="read-write">
  <a class="anchor inpage" href="#read-write">##</a>read, write</h2>
<h3 id="read">
  <a class="anchor inpage" href="#read">###</a>read</h3>
<h4 id="read-in-console">
  <a class="anchor inpage" href="#read-in-console">####</a>read in console</h4>
<details open>
    <summary>bash</summary><pre
        class="chroma codeblock"
      ><code class="language-bash" data-lang="bash"
          ><span style="display:flex;"><span>echo <span style="color:#e6db74">&#34;input a&#34;</span>
</span></span><span style="display:flex;"><span>read a
</span></span><span style="display:flex;"><span>echo <span style="color:#e6db74">&#34;input b&#34;</span>
</span></span><span style="display:flex;"><span>read b
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>read -n <span style="color:#ae81ff">3</span> -t <span style="color:#ae81ff">5</span> -s -p <span style="color:#e6db74">&#34;input 3 charater, wait for 5 seconds, silent&#34;</span> c
</span></span><span style="display:flex;"><span>echo <span style="color:#e6db74">&#34;</span>$c<span style="color:#e6db74">&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>printf <span style="color:#e6db74">&#34;a=%s,b=%s,sum is %s&#34;</span> $a $b <span style="color:#66d9ef">$((</span>a <span style="color:#f92672">+</span> b<span style="color:#66d9ef">))</span></span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><p>It is possible to give arguments to the script on execution.</p>
<p><code>$@</code> is a list of the parameters.</p>
<details open>
    <summary>bash</summary><pre
        class="chroma codeblock"
      ><code class="language-bash" data-lang="bash"
          ><span style="display:flex;"><span><span style="color:#75715e">#!/bin/bash
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">for</span> x in $@
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">do</span>
</span></span><span style="display:flex;"><span>    echo <span style="color:#e6db74">&#34;Entered arg is </span>$x<span style="color:#e6db74">&#34;</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">done</span></span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><p>Run it like this:</p>
<p><code>./script arg1 arg2</code></p>
<h4 id="read-in-file">
  <a class="anchor inpage" href="#read-in-file">####</a>read in file</h4>
<p>Suppose we have a file <code>sample_file.txt</code>, We can read the file line by line and print the output on the screen.</p>
<details open>
    <summary>bash</summary><pre
        class="chroma codeblock"
      ><code class="language-bash" data-lang="bash"
          ><span style="display:flex;"><span><span style="color:#75715e">#!/bin/bash
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span>LINE<span style="color:#f92672">=</span><span style="color:#ae81ff">1</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">while</span> read -r CURRENT_LINE
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">do</span>
</span></span><span style="display:flex;"><span>        echo <span style="color:#e6db74">&#34;</span>$LINE<span style="color:#e6db74">: </span>$CURRENT_LINE<span style="color:#e6db74">&#34;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">((</span>LINE++<span style="color:#f92672">))</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">done</span> &lt; <span style="color:#e6db74">&#34;sample_file.txt&#34;</span></span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><h3 id="write">
  <a class="anchor inpage" href="#write">###</a>write</h3>
<h2 id="redirection-pipe">
  <a class="anchor inpage" href="#redirection-pipe">##</a>redirection, pipe</h2>
<h3 id="direction">
  <a class="anchor inpage" href="#direction">###</a>direction</h3>
<h4 id="输出重定向">
  <a class="anchor inpage" href="#%e8%be%93%e5%87%ba%e9%87%8d%e5%ae%9a%e5%90%91">####</a>输出重定向</h4>
<table>
  <thead>
      <tr>
          <th>符号</th>
          <th>作用</th>
          <th>示例</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><code>&gt;</code></td>
          <td>覆盖写入文件（标准输出）</td>
          <td><code>ls &gt; file.txt</code></td>
      </tr>
      <tr>
          <td><code>&gt;&gt;</code></td>
          <td>追加到文件（标准输出）</td>
          <td><code>echo &quot;hi&quot; &gt;&gt; file.txt</code></td>
      </tr>
      <tr>
          <td><code>2&gt;</code></td>
          <td>覆盖写入文件（标准错误）</td>
          <td><code>cmd 2&gt; error.log</code></td>
      </tr>
      <tr>
          <td><code>2&gt;&gt;</code></td>
          <td>追加到文件（标准错误）</td>
          <td><code>cmd 2&gt;&gt; error.log</code></td>
      </tr>
      <tr>
          <td><code>&amp;&gt;</code></td>
          <td>覆盖写入文件（标准输出+标准错误）</td>
          <td><code>cmd &amp;&gt; output.log</code></td>
      </tr>
      <tr>
          <td><code>&amp;&gt;&gt;</code></td>
          <td>追加到文件（标准输出+标准错误）</td>
          <td><code>cmd &amp;&gt;&gt; output.log</code></td>
      </tr>
  </tbody>
</table>
<p><strong>文件描述符操作</strong> Bash 用数字<code>n</code>表示文件描述符（File Descriptor, FD）：</p>
<ul>
<li><code>0</code>：标准输入（stdin）</li>
<li><code>1</code>：标准输出（stdout）</li>
<li><code>2</code>：标准错误（stderr）</li>
</ul>
<table>
  <thead>
      <tr>
          <th>符号</th>
          <th>作用</th>
          <th>示例</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><code>n&gt;</code></td>
          <td>覆盖写入到文件描述符 <code>n</code></td>
          <td><code>cmd 3&gt; custom_fd.log</code></td>
      </tr>
      <tr>
          <td><code>n&gt;&gt;</code></td>
          <td>追加到文件描述符 <code>n</code></td>
          <td><code>cmd 3&gt;&gt; custom_fd.log</code></td>
      </tr>
      <tr>
          <td><code>n&gt;&amp;m</code></td>
          <td>将文件描述符 <code>n</code> 重定向到 <code>m</code></td>
          <td><code>cmd 2&gt;&amp;1</code>（错误合并到输出）</td>
      </tr>
      <tr>
          <td><code>n&gt;&amp;-</code></td>
          <td>关闭文件描述符 <code>n</code></td>
          <td><code>exec 3&gt;&amp;-</code></td>
      </tr>
      <tr>
          <td><code>&amp;&gt;file</code> 或 <code>&gt;&amp;file</code></td>
          <td>合并标准输出和错误到文件（兼容性写法）</td>
          <td><code>cmd &amp;&gt; all.log</code></td>
      </tr>
  </tbody>
</table>
<p><strong>示例</strong>：</p>
<details open>
    <summary>bash</summary><pre
        class="chroma codeblock"
      ><code class="language-bash" data-lang="bash"
          ><span style="display:flex;"><span><span style="color:#75715e"># 将标准错误重定向到文件描述符3，再重定向到文件</span>
</span></span><span style="display:flex;"><span>exec 3&gt;&amp;<span style="color:#ae81ff">1</span>  <span style="color:#75715e"># 备份标准输出到3</span>
</span></span><span style="display:flex;"><span>cmd 2&gt;&amp;<span style="color:#ae81ff">1</span> &gt;output.log | tee -a error.log  <span style="color:#75715e"># 错误流单独处理</span>
</span></span><span style="display:flex;"><span>exec 1&gt;&amp;<span style="color:#ae81ff">3</span>  <span style="color:#75715e"># 恢复标准输出</span></span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><p><strong>特殊设备重定向</strong></p>
<table>
  <thead>
      <tr>
          <th>目标文件</th>
          <th>作用</th>
          <th>示例</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><code>/dev/null</code></td>
          <td>丢弃输出（黑洞设备）</td>
          <td><code>cmd &gt; /dev/null 2&gt;&amp;1</code></td>
      </tr>
      <tr>
          <td><code>/dev/stdout</code></td>
          <td>显式指向标准输出</td>
          <td><code>echo &quot;x&quot; &gt; /dev/stdout</code></td>
      </tr>
      <tr>
          <td><code>/dev/stderr</code></td>
          <td>显式指向标准错误</td>
          <td><code>echo &quot;error&quot; &gt; /dev/stderr</code></td>
      </tr>
      <tr>
          <td><code>/dev/fd/n</code></td>
          <td>重定向到文件描述符 <code>n</code></td>
          <td><code>cmd &gt; /dev/fd/3</code></td>
      </tr>
  </tbody>
</table>
<p><strong>示例</strong>：</p>
<details open>
    <summary>bash</summary><pre
        class="chroma codeblock"
      ><code class="language-bash" data-lang="bash"
          ><span style="display:flex;"><span><span style="color:#75715e"># 静默执行命令（忽略所有输出）</span>
</span></span><span style="display:flex;"><span>cmd &gt; /dev/null 2&gt;&amp;<span style="color:#ae81ff">1</span></span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><h4 id="输入重定向">
  <a class="anchor inpage" href="#%e8%be%93%e5%85%a5%e9%87%8d%e5%ae%9a%e5%90%91">####</a>输入重定向</h4>
<table>
  <thead>
      <tr>
          <th>符号</th>
          <th>作用</th>
          <th>示例</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><code>&lt;</code></td>
          <td>从文件读取输入（标准输入）</td>
          <td><code>sort &lt; data.txt</code></td>
      </tr>
      <tr>
          <td><code>&lt;&lt;</code></td>
          <td>Here Document（多行输入）</td>
          <td>见前文</td>
      </tr>
      <tr>
          <td><code>&lt;&lt;&lt;</code></td>
          <td>Here String（字符串输入）</td>
          <td><code>grep &quot;x&quot; &lt;&lt;&lt; &quot;abc&quot;</code></td>
      </tr>
  </tbody>
</table>
<p><strong><code>&lt;</code>：标准输入重定向</strong></p>
<p><strong>作用</strong>：将文件内容作为命令的标准输入。<br>
<strong>语法</strong>：<code>command &lt; file</code><br>
<strong>特点</strong>：</p>
<ul>
<li>从文件中读取数据并传递给命令</li>
<li>文件内容会逐行作为命令的输入</li>
</ul>
<p><strong>示例</strong>：</p>
<details open>
    <summary>bash</summary><pre
        class="chroma codeblock"
      ><code class="language-bash" data-lang="bash"
          ><span style="display:flex;"><span><span style="color:#75715e"># 将 file.txt 的内容作为 wc 命令的输入</span>
</span></span><span style="display:flex;"><span>wc -l &lt; file.txt</span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><p><strong>结果</strong>：统计 <code>file.txt</code> 的行数。</p>
<p><strong><code>&lt;&lt;</code>：Here Document（文档内嵌输入）</strong></p>
<p><strong>作用</strong>：将多行文本（称为 &ldquo;Here Document&rdquo;）作为命令的标准输入，直到遇到指定的结束标记。<br>
<strong>语法</strong>：</p>
<details open>
    <summary>bash</summary><pre
        class="chroma codeblock"
      ><code class="language-bash" data-lang="bash"
          ><span style="display:flex;"><span>command <span style="color:#e6db74">&lt;&lt; DELIMITER
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">多行文本...
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">DELIMITER</span></span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><p><strong>特点</strong>：</p>
<ul>
<li>允许在脚本中直接嵌入多行输入</li>
<li>结束标记（<code>DELIMITER</code>）可以是任意字符串（通常用 <code>EOF</code>）</li>
<li>默认会解析变量和命令替换（除非用引号包围 <code>DELIMITER</code>，如 <code>&lt;&lt;'EOF'</code>）</li>
</ul>
<p><strong>示例</strong>：</p>
<details open>
    <summary>bash</summary><pre
        class="chroma codeblock"
      ><code class="language-bash" data-lang="bash"
          ><span style="display:flex;"><span><span style="color:#75715e"># 将多行文本传递给 cat 命令</span>
</span></span><span style="display:flex;"><span>cat <span style="color:#e6db74">&lt;&lt; EOF
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">第一行
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">第二行
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">变量值: $HOME
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">EOF</span></span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><p><strong>结果</strong>：</p>
<details open>
    <summary>TEXT</summary><pre
        class="codeblock"
      ><code class="language-" data-lang="">第一行
第二行
变量值: /home/username</code><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><p><strong><code>&lt;&lt;&lt;</code>：Here String（字符串内嵌输入）</strong>
<strong>作用</strong>：将单个字符串作为命令的标准输入。<br>
<strong>语法</strong>：<code>command &lt;&lt;&lt; &quot;string&quot;</code><br>
<strong>特点</strong>：</p>
<ul>
<li>直接传递字符串（无需文件或多行文本）</li>
<li>字符串会解析变量和命令替换</li>
<li>比 <code>echo &quot;string&quot; | command</code> 更高效（避免管道和子进程）</li>
</ul>
<p><strong>示例</strong>：</p>
<details open>
    <summary>bash</summary><pre
        class="chroma codeblock"
      ><code class="language-bash" data-lang="bash"
          ><span style="display:flex;"><span><span style="color:#75715e"># 将字符串传递给 grep 命令</span>
</span></span><span style="display:flex;"><span>grep <span style="color:#e6db74">&#34;hello&#34;</span> <span style="color:#f92672">&lt;&lt;&lt;</span> <span style="color:#e6db74">&#34;hello world&#34;</span></span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><p><strong>结果</strong>：输出 <code>hello world</code>（因为匹配成功）。</p>
<p><strong>对比总结</strong></p>
<table>
  <thead>
      <tr>
          <th>操作符</th>
          <th>名称</th>
          <th>输入源</th>
          <th>典型用途</th>
          <th>是否解析变量</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><code>&lt;</code></td>
          <td>输入重定向</td>
          <td>文件</td>
          <td>从文件读取数据</td>
          <td>是</td>
      </tr>
      <tr>
          <td><code>&lt;&lt;</code></td>
          <td>Here Document</td>
          <td>多行文本（脚本内嵌）</td>
          <td>传递多行输入（如生成配置文件）</td>
          <td>是（可禁用）</td>
      </tr>
      <tr>
          <td><code>&lt;&lt;&lt;</code></td>
          <td>Here String</td>
          <td>单个字符串</td>
          <td>快速传递变量或简单字符串</td>
          <td>是</td>
      </tr>
  </tbody>
</table>
<p><strong>关键区别</strong></p>
<ol>
<li>
<p><strong>输入来源不同</strong>：</p>
<ul>
<li><code>&lt;</code> 从文件读取</li>
<li><code>&lt;&lt;</code> 从脚本内嵌的多行文本读取</li>
<li><code>&lt;&lt;&lt;</code> 从单个字符串读取</li>
</ul>
</li>
<li>
<p><strong>性能差异</strong>：</p>
<ul>
<li><code>&lt;&lt;&lt;</code> 比 <code>echo &quot;str&quot; | command</code> 更高效（避免管道）</li>
<li><code>&lt;</code> 适合处理大文件（逐行读取，不占用内存）</li>
</ul>
</li>
<li>
<p><strong>变量解析</strong>：</p>
<ul>
<li><code>&lt;&lt;</code> 和 <code>&lt;&lt;&lt;</code> 默认解析变量，但 <code>&lt;&lt;</code> 可通过 <code>&lt;&lt;'DELIMITER'</code> 禁用解析</li>
<li><code>&lt;</code> 由命令决定是否解析（如 <code>cat</code> 不解析，<code>eval</code> 会解析）</li>
</ul>
</li>
</ol>
<hr>
<p><strong>使用场景示例</strong>
<strong><code>&lt;</code> 的典型用途</strong></p>
<details open>
    <summary>bash</summary><pre
        class="chroma codeblock"
      ><code class="language-bash" data-lang="bash"
          ><span style="display:flex;"><span><span style="color:#75715e"># 从配置文件读取输入</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">while</span> read line; <span style="color:#66d9ef">do</span>
</span></span><span style="display:flex;"><span>    echo <span style="color:#e6db74">&#34;配置行: </span>$line<span style="color:#e6db74">&#34;</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">done</span> &lt; config.txt</span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><p><strong><code>&lt;&lt;</code> 的典型用途</strong></p>
<details open>
    <summary>bash</summary><pre
        class="chroma codeblock"
      ><code class="language-bash" data-lang="bash"
          ><span style="display:flex;"><span><span style="color:#75715e"># 生成多行配置文件</span>
</span></span><span style="display:flex;"><span>cat &gt; app.conf <span style="color:#e6db74">&lt;&lt; EOF
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">server_ip=192.168.1.1
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">port=8080
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">EOF</span></span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><p><strong><code>&lt;&lt;&lt;</code> 的典型用途</strong></p>
<details open>
    <summary>bash</summary><pre
        class="chroma codeblock"
      ><code class="language-bash" data-lang="bash"
          ><span style="display:flex;"><span><span style="color:#75715e"># 快速检查字符串是否包含子串</span>
</span></span><span style="display:flex;"><span>grep <span style="color:#e6db74">&#34;error&#34;</span> <span style="color:#f92672">&lt;&lt;&lt;</span> <span style="color:#e6db74">&#34;</span>$log_content<span style="color:#e6db74">&#34;</span></span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><p><strong>注意事项</strong></p>
<ol>
<li>
<p><strong><code>&lt;&lt;</code> 的结束标记</strong>：</p>
<ul>
<li>结束标记必须单独一行且顶格书写（不能有缩进）：
<details open>
    <summary>bash</summary><pre
        class="chroma codeblock"
      ><code class="language-bash" data-lang="bash"
          ><span style="display:flex;"><span><span style="color:#75715e"># 错误示例（缩进会导致语法错误）</span>
</span></span><span style="display:flex;"><span>cat <span style="color:#e6db74">&lt;&lt; EOF
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">内容...
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">  EOF</span>  <span style="color:#75715e"># 缩进了，无法识别为结束标记</span></span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script></li>
</ul>
</li>
<li>
<p><strong><code>&lt;&lt;&lt;</code> 的字符串引用</strong>：</p>
<ul>
<li>如果字符串包含空格或特殊字符，需用引号包围：
<details open>
    <summary>bash</summary><pre
        class="chroma codeblock"
      ><code class="language-bash" data-lang="bash"
          ><span style="display:flex;"><span><span style="color:#75715e"># 安全写法</span>
</span></span><span style="display:flex;"><span>wc -w <span style="color:#f92672">&lt;&lt;&lt;</span> <span style="color:#e6db74">&#34;hello world&#34;</span></span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script></li>
</ul>
</li>
<li>
<p><strong>性能选择</strong>：</p>
<ul>
<li>处理大量数据时优先用 <code>&lt;</code>（文件）或 <code>&lt;&lt;</code>（多行文本）</li>
<li>简单字符串操作用 <code>&lt;&lt;&lt;</code> 更高效</li>
</ul>
</li>
</ol>
<h4 id="重定向组合">
  <a class="anchor inpage" href="#%e9%87%8d%e5%ae%9a%e5%90%91%e7%bb%84%e5%90%88">####</a>重定向组合</h4>
<p><strong>(1) 同时重定向输入和输出</strong></p>
<details open>
    <summary>bash</summary><pre
        class="chroma codeblock"
      ><code class="language-bash" data-lang="bash"
          ><span style="display:flex;"><span><span style="color:#75715e"># 从input.txt读取，结果写入output.txt</span>
</span></span><span style="display:flex;"><span>command &lt; input.txt &gt; output.txt</span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><p><strong>(2) 分离标准输出和错误</strong></p>
<details open>
    <summary>bash</summary><pre
        class="chroma codeblock"
      ><code class="language-bash" data-lang="bash"
          ><span style="display:flex;"><span><span style="color:#75715e"># 标准输出到out.log，错误到err.log</span>
</span></span><span style="display:flex;"><span>command &gt; out.log 2&gt; err.log</span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><p><strong>(3) 合并输出和错误到同一文件</strong></p>
<details open>
    <summary>bash</summary><pre
        class="chroma codeblock"
      ><code class="language-bash" data-lang="bash"
          ><span style="display:flex;"><span><span style="color:#75715e"># 方式1（推荐）</span>
</span></span><span style="display:flex;"><span>command &amp;&gt; combined.log
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># 方式2（传统写法）</span>
</span></span><span style="display:flex;"><span>command &gt; combined.log 2&gt;&amp;<span style="color:#ae81ff">1</span></span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><h4 id="进程替换process-substitution">
  <a class="anchor inpage" href="#%e8%bf%9b%e7%a8%8b%e6%9b%bf%e6%8d%a2process-substitution">####</a>进程替换（Process Substitution）</h4>
<p>用 <code>&gt;(...)</code> 和 <code>&lt;(...)</code> 将命令输出/输入视为临时文件：</p>
<table>
  <thead>
      <tr>
          <th>符号</th>
          <th>作用</th>
          <th>示例</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><code>&lt;(cmd)</code></td>
          <td>将命令输出作为文件输入</td>
          <td><code>diff &lt;(ls dir1) &lt;(ls dir2)</code></td>
      </tr>
      <tr>
          <td><code>&gt;(cmd)</code></td>
          <td>将命令输入作为文件输出</td>
          <td><code>tee &gt;(gzip &gt; out.gz)</code></td>
      </tr>
  </tbody>
</table>
<p><strong>示例</strong>：</p>
<details open>
    <summary>bash</summary><pre
        class="chroma codeblock"
      ><code class="language-bash" data-lang="bash"
          ><span style="display:flex;"><span><span style="color:#75715e"># 比较两个目录的文件列表差异</span>
</span></span><span style="display:flex;"><span>diff &lt;<span style="color:#f92672">(</span>ls /path/to/dir1<span style="color:#f92672">)</span> &lt;<span style="color:#f92672">(</span>ls /path/to/dir2<span style="color:#f92672">)</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># 将输出同时写入文件和压缩</span>
</span></span><span style="display:flex;"><span>echo <span style="color:#e6db74">&#34;data&#34;</span> | tee &gt;<span style="color:#f92672">(</span>gzip &gt; output.gz<span style="color:#f92672">)</span> &gt; original.txt</span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><h4 id="综合示例">
  <a class="anchor inpage" href="#%e7%bb%bc%e5%90%88%e7%a4%ba%e4%be%8b">####</a>综合示例</h4>
<p>** 日志记录脚本**</p>
<details open>
    <summary>bash</summary><pre
        class="chroma codeblock"
      ><code class="language-bash" data-lang="bash"
          ><span style="display:flex;"><span><span style="color:#75715e">#!/bin/bash
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>exec 3&gt;&amp;<span style="color:#ae81ff">1</span>  <span style="color:#75715e"># 备份标准输出到描述符3</span>
</span></span><span style="display:flex;"><span>exec &gt; &gt;<span style="color:#f92672">(</span>tee -a stdout.log<span style="color:#f92672">)</span> 2&gt; &gt;<span style="color:#f92672">(</span>tee -a stderr.log &gt;&amp;2<span style="color:#f92672">)</span>  <span style="color:#75715e"># 分离输出和错误</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>echo <span style="color:#e6db74">&#34;正常消息&#34;</span>  <span style="color:#75715e"># 写入stdout.log</span>
</span></span><span style="display:flex;"><span>ls /nonexistent  <span style="color:#75715e"># 错误写入stderr.log</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>exec 1&gt;&amp;<span style="color:#ae81ff">3</span>  <span style="color:#75715e"># 恢复标准输出</span>
</span></span><span style="display:flex;"><span>echo <span style="color:#e6db74">&#34;回到终端显示&#34;</span></span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><p><strong>复杂重定向</strong></p>
<details open>
    <summary>bash</summary><pre
        class="chroma codeblock"
      ><code class="language-bash" data-lang="bash"
          ><span style="display:flex;"><span><span style="color:#f92672">{</span>
</span></span><span style="display:flex;"><span>    echo <span style="color:#e6db74">&#34;标准输出1&#34;</span>
</span></span><span style="display:flex;"><span>    echo <span style="color:#e6db74">&#34;标准错误1&#34;</span> &gt;&amp;<span style="color:#ae81ff">2</span>
</span></span><span style="display:flex;"><span>    echo <span style="color:#e6db74">&#34;标准输出2&#34;</span>
</span></span><span style="display:flex;"><span>    echo <span style="color:#e6db74">&#34;标准错误2&#34;</span> &gt;&amp;<span style="color:#ae81ff">2</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">}</span> &gt; &gt;<span style="color:#f92672">(</span>grep <span style="color:#e6db74">&#34;标准输出&#34;</span> &gt; out.txt<span style="color:#f92672">)</span> 2&gt; &gt;<span style="color:#f92672">(</span>grep <span style="color:#e6db74">&#34;标准错误&#34;</span> &gt; err.txt<span style="color:#f92672">)</span></span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><p><strong>注意事项</strong></p>
<ol>
<li>
<p><strong>顺序敏感</strong>：<br>
<code>2&gt;&amp;1 &gt;file</code> 和 <code>&gt;file 2&gt;&amp;1</code> 完全不同！后者才是合并输出到文件。</p>
<details open>
    <summary>bash</summary><pre
        class="chroma codeblock"
      ><code class="language-bash" data-lang="bash"
          ><span style="display:flex;"><span><span style="color:#75715e"># 错误：错误流不会进入文件</span>
</span></span><span style="display:flex;"><span>cmd 2&gt;&amp;<span style="color:#ae81ff">1</span> &gt; file
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># 正确：合并输出和错误到文件</span>
</span></span><span style="display:flex;"><span>cmd &gt; file 2&gt;&amp;<span style="color:#ae81ff">1</span></span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script></li>
<li>
<p><strong>文件描述符范围</strong>：<br>
Bash 默认支持 <code>0-9</code>，更高数值需用 <code>exec</code> 显式分配。</p>
</li>
<li>
<p><strong>管道与重定向优先级</strong>：<br>
管道 <code>|</code> 优先级高于重定向，必要时用 <code>{ }</code> 分组：</p>
<details open>
    <summary>bash</summary><pre
        class="chroma codeblock"
      ><code class="language-bash" data-lang="bash"
          ><span style="display:flex;"><span><span style="color:#f92672">{</span> cmd1 | cmd2; <span style="color:#f92672">}</span> &gt; output.txt</span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script></li>
<li>
<p><strong>Here Document 的变体</strong>：</p>
<ul>
<li><code>&lt;&lt;-</code>：忽略结束标记前的制表符（Tab）
<details open>
    <summary>bash</summary><pre
        class="chroma codeblock"
      ><code class="language-bash" data-lang="bash"
          ><span style="display:flex;"><span>cat <span style="color:#e6db74">&lt;&lt;- EOF
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    Indented text
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">EOF</span>  <span style="color:#75715e"># 可以用Tab缩进</span></span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script></li>
</ul>
</li>
</ol>
<h3 id="pipe">
  <a class="anchor inpage" href="#pipe">###</a>pipe</h3>
<h2 id="control">
  <a class="anchor inpage" href="#control">##</a>control</h2>
<h3 id="if">
  <a class="anchor inpage" href="#if">###</a>if</h3>
<ul>
<li><code>if...then...fi</code> statements</li>
<li><code>if...then...else...fi</code> statements</li>
<li><code>if..elif..else..fi</code></li>
<li><code>if..then..else..if..then..fi..fi..</code> (Nested Conditionals)</li>
</ul>
<details open>
    <summary>bash</summary><pre
        class="chroma codeblock"
      ><code class="language-bash" data-lang="bash"
          ><span style="display:flex;"><span><span style="color:#66d9ef">if</span> <span style="color:#f92672">[</span> ... <span style="color:#f92672">]</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">then</span>
</span></span><span style="display:flex;"><span>  <span style="color:#75715e"># if-code</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">else</span>
</span></span><span style="display:flex;"><span>  <span style="color:#75715e"># else-code</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">fi</span></span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><p>or</p>
<details open>
    <summary>bash</summary><pre
        class="chroma codeblock"
      ><code class="language-bash" data-lang="bash"
          ><span style="display:flex;"><span><span style="color:#66d9ef">if</span> <span style="color:#f92672">[</span> ... <span style="color:#f92672">]</span> ; <span style="color:#66d9ef">then</span>
</span></span><span style="display:flex;"><span>  <span style="color:#75715e"># if-code</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">else</span>
</span></span><span style="display:flex;"><span>  <span style="color:#75715e"># else-code</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">fi</span></span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><p>conditions:</p>
<p>examples:</p>
<details open>
    <summary>bash</summary><pre
        class="chroma codeblock"
      ><code class="language-bash" data-lang="bash"
          ><span style="display:flex;"><span><span style="color:#75715e">#!/bin/sh
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span><span style="color:#66d9ef">if</span> <span style="color:#f92672">[</span> <span style="color:#e6db74">&#34;</span>$X<span style="color:#e6db74">&#34;</span> -lt <span style="color:#e6db74">&#34;0&#34;</span> <span style="color:#f92672">]</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">then</span>
</span></span><span style="display:flex;"><span>  echo <span style="color:#e6db74">&#34;X is less than zero&#34;</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">fi</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">if</span> <span style="color:#f92672">[</span> <span style="color:#e6db74">&#34;</span>$X<span style="color:#e6db74">&#34;</span> -gt <span style="color:#e6db74">&#34;0&#34;</span> <span style="color:#f92672">]</span>; <span style="color:#66d9ef">then</span>
</span></span><span style="display:flex;"><span>  echo <span style="color:#e6db74">&#34;X is more than zero&#34;</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">fi</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">[</span> <span style="color:#e6db74">&#34;</span>$X<span style="color:#e6db74">&#34;</span> -le <span style="color:#e6db74">&#34;0&#34;</span> <span style="color:#f92672">]</span> <span style="color:#f92672">&amp;&amp;</span> <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>      echo <span style="color:#e6db74">&#34;X is less than or equal to  zero&#34;</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">[</span> <span style="color:#e6db74">&#34;</span>$X<span style="color:#e6db74">&#34;</span> -ge <span style="color:#e6db74">&#34;0&#34;</span> <span style="color:#f92672">]</span> <span style="color:#f92672">&amp;&amp;</span> <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>      echo <span style="color:#e6db74">&#34;X is more than or equal to zero&#34;</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">[</span> <span style="color:#e6db74">&#34;</span>$X<span style="color:#e6db74">&#34;</span> <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;0&#34;</span> <span style="color:#f92672">]</span> <span style="color:#f92672">&amp;&amp;</span> <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>      echo <span style="color:#e6db74">&#34;X is the string or number \&#34;0\&#34;&#34;</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">[</span> <span style="color:#e6db74">&#34;</span>$X<span style="color:#e6db74">&#34;</span> <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;hello&#34;</span> <span style="color:#f92672">]</span> <span style="color:#f92672">&amp;&amp;</span> <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>      echo <span style="color:#e6db74">&#34;X matches the string \&#34;hello\&#34;&#34;</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">[</span> <span style="color:#e6db74">&#34;</span>$X<span style="color:#e6db74">&#34;</span> !<span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;hello&#34;</span> <span style="color:#f92672">]</span> <span style="color:#f92672">&amp;&amp;</span> <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>      echo <span style="color:#e6db74">&#34;X is not the string \&#34;hello\&#34;&#34;</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">[</span> -n <span style="color:#e6db74">&#34;</span>$X<span style="color:#e6db74">&#34;</span> <span style="color:#f92672">]</span> <span style="color:#f92672">&amp;&amp;</span> <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>      echo <span style="color:#e6db74">&#34;X is of nonzero length&#34;</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">[</span> -f <span style="color:#e6db74">&#34;</span>$X<span style="color:#e6db74">&#34;</span> <span style="color:#f92672">]</span> <span style="color:#f92672">&amp;&amp;</span> <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>      echo <span style="color:#e6db74">&#34;X is the path of a real file&#34;</span> <span style="color:#f92672">||</span> <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>      echo <span style="color:#e6db74">&#34;No such file: </span>$X<span style="color:#e6db74">&#34;</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">[</span> -x <span style="color:#e6db74">&#34;</span>$X<span style="color:#e6db74">&#34;</span> <span style="color:#f92672">]</span> <span style="color:#f92672">&amp;&amp;</span> <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>      echo <span style="color:#e6db74">&#34;X is the path of an executable file&#34;</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">[</span> <span style="color:#e6db74">&#34;</span>$X<span style="color:#e6db74">&#34;</span> -nt <span style="color:#e6db74">&#34;/etc/passwd&#34;</span> <span style="color:#f92672">]</span> <span style="color:#f92672">&amp;&amp;</span> <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>      echo <span style="color:#e6db74">&#34;X is a file which is newer than /etc/passwd&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>read a
</span></span><span style="display:flex;"><span>read b
</span></span><span style="display:flex;"><span>read c
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">if</span> <span style="color:#f92672">[</span> $a <span style="color:#f92672">==</span> $b -a $b <span style="color:#f92672">==</span> $c -a $a <span style="color:#f92672">==</span> $c <span style="color:#f92672">]</span> <span style="color:#75715e"># -a means</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">then</span>
</span></span><span style="display:flex;"><span>echo EQUILATERAL
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">elif</span> <span style="color:#f92672">[</span> $a <span style="color:#f92672">==</span> $b -o $b <span style="color:#f92672">==</span> $c -o $a <span style="color:#f92672">==</span> $c <span style="color:#f92672">]</span> <span style="color:#75715e"># -o means or</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">then</span>
</span></span><span style="display:flex;"><span>echo ISOSCELES
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">else</span>
</span></span><span style="display:flex;"><span>echo SCALENE
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">fi</span></span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><h3 id="loop">
  <a class="anchor inpage" href="#loop">###</a>loop</h3>
<details open>
    <summary>bash</summary><pre
        class="chroma codeblock"
      ><code class="language-bash" data-lang="bash"
          ><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">for</span> i in <span style="color:#f92672">{</span>1..5<span style="color:#f92672">}</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">do</span>
</span></span><span style="display:flex;"><span>    echo $i
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">done</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">for</span> X in cyan magenta yellow
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">do</span>
</span></span><span style="display:flex;"><span>    echo $X
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">done</span></span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><details open>
    <summary>bash</summary><pre
        class="chroma codeblock"
      ><code class="language-bash" data-lang="bash"
          ><span style="display:flex;"><span>i<span style="color:#f92672">=</span><span style="color:#ae81ff">1</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">while</span> <span style="color:#f92672">[[</span> $i -le <span style="color:#ae81ff">10</span> <span style="color:#f92672">]]</span> ; <span style="color:#66d9ef">do</span>
</span></span><span style="display:flex;"><span>   echo <span style="color:#e6db74">&#34;</span>$i<span style="color:#e6db74">&#34;</span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">((</span> i <span style="color:#f92672">+=</span> <span style="color:#ae81ff">1</span> <span style="color:#f92672">))</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">done</span></span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><details open>
    <summary>bash</summary><pre
        class="chroma codeblock"
      ><code class="language-bash" data-lang="bash"
          ><span style="display:flex;"><span><span style="color:#75715e"># 定义数组（空格分隔元素，可含特殊字符）</span>
</span></span><span style="display:flex;"><span>fruits<span style="color:#f92672">=(</span><span style="color:#e6db74">&#34;Apple&#34;</span> <span style="color:#e6db74">&#34;Banana&#34;</span> <span style="color:#e6db74">&#34;Orange&#34;</span> <span style="color:#e6db74">&#34;Grape&#34;</span> <span style="color:#e6db74">&#34;Watermelon&#34;</span><span style="color:#f92672">)</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">for</span> fruit in <span style="color:#e6db74">&#34;</span><span style="color:#e6db74">${</span>fruits[@]<span style="color:#e6db74">}</span><span style="color:#e6db74">&#34;</span>; <span style="color:#66d9ef">do</span>
</span></span><span style="display:flex;"><span>    echo <span style="color:#e6db74">&#34;Fruit: </span>$fruit<span style="color:#e6db74">&#34;</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">done</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">for</span> i in <span style="color:#e6db74">&#34;</span><span style="color:#e6db74">${</span>!fruits[@]<span style="color:#e6db74">}</span><span style="color:#e6db74">&#34;</span>; <span style="color:#66d9ef">do</span>
</span></span><span style="display:flex;"><span>    echo <span style="color:#e6db74">&#34;Index </span>$i<span style="color:#e6db74">: </span><span style="color:#e6db74">${</span>fruits[i]<span style="color:#e6db74">}</span><span style="color:#e6db74">&#34;</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">done</span></span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><details open>
    <summary>bash</summary><pre
        class="chroma codeblock"
      ><code class="language-bash" data-lang="bash"
          ><span style="display:flex;"><span><span style="color:#75715e"># 定义仓库目录列表（支持绝对路径或相对路径）</span>
</span></span><span style="display:flex;"><span>repos<span style="color:#f92672">=(</span>
</span></span><span style="display:flex;"><span>    <span style="color:#e6db74">&#34;/path/to/repo1&#34;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#e6db74">&#34;/path/to/repo2&#34;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#e6db74">&#34;/path/to/repo3&#34;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#e6db74">&#34;/path/to/repo4&#34;</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">)</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># 遍历所有仓库</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">for</span> i in <span style="color:#e6db74">&#34;</span><span style="color:#e6db74">${</span>repos[@]<span style="color:#e6db74">}</span><span style="color:#e6db74">&#34;</span>; <span style="color:#66d9ef">do</span>
</span></span><span style="display:flex;"><span>    echo <span style="color:#e6db74">&#34;Updating repo: </span>$i<span style="color:#e6db74">&#34;</span>
</span></span><span style="display:flex;"><span>    cd <span style="color:#e6db74">&#34;</span>$i<span style="color:#e6db74">&#34;</span> <span style="color:#f92672">||</span> <span style="color:#f92672">{</span> echo <span style="color:#e6db74">&#34;Failed to enter </span>$i<span style="color:#e6db74">&#34;</span>; <span style="color:#66d9ef">continue</span>; <span style="color:#f92672">}</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e"># 执行 git pull</span>
</span></span><span style="display:flex;"><span>    git pull origin main  <span style="color:#75715e"># 假设分支是 main，根据实际情况修改</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e"># 检查 git pull 是否成功</span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">if</span> <span style="color:#f92672">[</span> $? -eq <span style="color:#ae81ff">0</span> <span style="color:#f92672">]</span>; <span style="color:#66d9ef">then</span>
</span></span><span style="display:flex;"><span>        echo <span style="color:#e6db74">&#34;Successfully updated: </span>$i<span style="color:#e6db74">&#34;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">else</span>
</span></span><span style="display:flex;"><span>        echo <span style="color:#e6db74">&#34;Failed to update: </span>$i<span style="color:#e6db74">&#34;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">fi</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    echo <span style="color:#e6db74">&#34;----------------------------------&#34;</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">done</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>echo <span style="color:#e6db74">&#34;All repositories updated!&#34;</span></span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><h2 id="function">
  <a class="anchor inpage" href="#function">##</a>function</h2>
<blockquote class="alert alert-warning">
      <p class="alert-heading"><br></p><p><strong>fork boom!</strong></p>
<details open>
    <summary>TEXT</summary><pre
        class="codeblock"
      ><code class="language-" data-lang="">:(){:|:;};:</code><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script></blockquote><h2 id="advance">
  <a class="anchor inpage" href="#advance">##</a>Advance</h2>
<h3 id="get-opts">
  <a class="anchor inpage" href="#get-opts">###</a>get-opts</h3>
<p>example:</p>
<details open>
    <summary>sh</summary><pre
        class="chroma codeblock"
      ><code class="language-sh" data-lang="sh"
          ><span style="display:flex;"><span><span style="color:#75715e">#!/bin/sh
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>docs<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;Usage: \
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">\n\tbash </span>$0<span style="color:#e6db74"> [options] \
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">\nOptions: \
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">\n\t-N NAME: your name, required\
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">\n\t-a AGE: your age, required\
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">\n\t-v: verbose mode, optional\
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">\nExample: \
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">\n\t bash </span>$0<span style="color:#e6db74"> -N balabala -a 24 &#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>usage<span style="color:#f92672">()</span> <span style="color:#f92672">{</span>
</span></span><span style="display:flex;"><span>    echo -e $docs &gt;&amp;<span style="color:#ae81ff">2</span>
</span></span><span style="display:flex;"><span>    exit <span style="color:#ae81ff">1</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">}</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">if</span> <span style="color:#f92672">[</span> $# -eq <span style="color:#ae81ff">0</span> <span style="color:#f92672">]</span> <span style="color:#f92672">||</span> <span style="color:#f92672">[</span> $1 <span style="color:#f92672">==</span> -h <span style="color:#f92672">]</span>; <span style="color:#66d9ef">then</span> usage; <span style="color:#66d9ef">fi</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">## 设置变量的默认值</span>
</span></span><span style="display:flex;"><span>verbose<span style="color:#f92672">=</span>n
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">## 检查变量参数是否缺失</span>
</span></span><span style="display:flex;"><span>check<span style="color:#f92672">()</span> <span style="color:#f92672">{</span>
</span></span><span style="display:flex;"><span>    opt<span style="color:#f92672">=</span>$1
</span></span><span style="display:flex;"><span>    arg<span style="color:#f92672">=</span>$2
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">if</span> <span style="color:#f92672">[[</span> $arg <span style="color:#f92672">=</span>~ ^- <span style="color:#f92672">]]</span> <span style="color:#f92672">||</span> <span style="color:#f92672">[</span> ! $arg <span style="color:#f92672">]</span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">then</span>
</span></span><span style="display:flex;"><span>        echo <span style="color:#e6db74">&#34;ERROR: -</span>$opt<span style="color:#e6db74"> expects an corresponding argument&#34;</span> &gt;&amp;<span style="color:#ae81ff">2</span>
</span></span><span style="display:flex;"><span>        usage
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">fi</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">}</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">## 循环解析脚本的所有positional parameters</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">while</span> getopts :vN:a: opt
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">do</span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">case</span> $opt in
</span></span><span style="display:flex;"><span>    v<span style="color:#f92672">)</span>
</span></span><span style="display:flex;"><span>        verbose<span style="color:#f92672">=</span>y
</span></span><span style="display:flex;"><span>        ;;
</span></span><span style="display:flex;"><span>    N<span style="color:#f92672">)</span>
</span></span><span style="display:flex;"><span>        check N $OPTARG
</span></span><span style="display:flex;"><span>        name<span style="color:#f92672">=</span>$OPTARG
</span></span><span style="display:flex;"><span>        ;;
</span></span><span style="display:flex;"><span>    a<span style="color:#f92672">)</span>
</span></span><span style="display:flex;"><span>        check a $OPTARG
</span></span><span style="display:flex;"><span>        age<span style="color:#f92672">=</span>$OPTARG
</span></span><span style="display:flex;"><span>        ;;
</span></span><span style="display:flex;"><span>    :<span style="color:#f92672">)</span>
</span></span><span style="display:flex;"><span>        echo <span style="color:#e6db74">&#34;ERROR: -</span>$OPTARG<span style="color:#e6db74"> expects an corresponding argument&#34;</span> &gt;&amp;<span style="color:#ae81ff">2</span>
</span></span><span style="display:flex;"><span>        usage
</span></span><span style="display:flex;"><span>        ;;
</span></span><span style="display:flex;"><span>    <span style="color:#ae81ff">\?</span><span style="color:#f92672">)</span> <span style="color:#75715e"># shell里&#39;?&#39;具有匹配一位任意字符的作用，因此需要转义为普通字符</span>
</span></span><span style="display:flex;"><span>        echo <span style="color:#e6db74">&#34;ERROR: unkown option -</span>$OPTARG<span style="color:#e6db74">&#34;</span> &gt;&amp;<span style="color:#ae81ff">2</span>
</span></span><span style="display:flex;"><span>        usage
</span></span><span style="display:flex;"><span>        ;;
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">esac</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">done</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">## 如果用户没有提供-N选项</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">if</span> <span style="color:#f92672">[</span> ! $name <span style="color:#f92672">]</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">then</span>
</span></span><span style="display:flex;"><span>    echo ERROR: option -N is required &gt;&amp;<span style="color:#ae81ff">2</span>
</span></span><span style="display:flex;"><span>    usage
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">fi</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">## 如果用户没有提供-a选项</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">if</span> <span style="color:#f92672">[</span> ! $age <span style="color:#f92672">]</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">then</span>
</span></span><span style="display:flex;"><span>    echo ERROR: option -a is required &gt;&amp;<span style="color:#ae81ff">2</span>
</span></span><span style="display:flex;"><span>    usage
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">fi</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">if</span> <span style="color:#f92672">[</span> $verbose <span style="color:#f92672">==</span> n <span style="color:#f92672">]</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">then</span>
</span></span><span style="display:flex;"><span>    echo <span style="color:#e6db74">&#34;Merry Christmas! </span>$name<span style="color:#e6db74">&#34;</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">else</span>
</span></span><span style="display:flex;"><span>    echo <span style="color:#e6db74">&#34;Hello, your name is </span>$name<span style="color:#e6db74">, you are </span>$age<span style="color:#e6db74"> years old!&#34;</span>
</span></span><span style="display:flex;"><span>    echo <span style="color:#e6db74">&#34;Merry Christmas!!&#34;</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">fi</span></span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><p>在 <code>:vN:a:</code>中，第一个<code>:</code> 表示静默错误模式（silent error mode）。如果没有这个<code>:</code>，当遇到无效选项时，getopts 会打印错误消息。<br>
选项后的 <code>:</code>（如 N:）表示该选项需要一个参数。<br>
如果没有 <code>:</code>，则表示该选项不需要参数。</p>
<h3 id="cron">
  <a class="anchor inpage" href="#cron">###</a>cron</h3>
<p>Cron is a job scheduling utility present in Unix like systems. You can schedule jobs to execute daily, weekly, monthly or in a specific time of the day. Automation in Linux heavily relies on cron jobs.</p>
<p>Below is the syntax to schedule crons:</p>
<details open>
    <summary>bash</summary><pre
        class="chroma codeblock"
      ><code class="language-bash" data-lang="bash"
          ><span style="display:flex;"><span><span style="color:#75715e"># Cron job example</span>
</span></span><span style="display:flex;"><span>* * * * * sh /path/to/script.sh</span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><p>Here, <code>*</code> represents minute(s) hour(s) day(s) month(s) weekday(s), respectively.</p>
<p>Below are some examples of scheduling cron jobs.</p>
<table>
  <thead>
      <tr>
          <th>SCHEDULE</th>
          <th>SCHEDULED VALUE</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>5 0 * 8 *</td>
          <td>At 00:05 in August.</td>
      </tr>
      <tr>
          <td>5 4 * * 6</td>
          <td>At 04:05 on Saturday.</td>
      </tr>
      <tr>
          <td>0 22 * * 1-5</td>
          <td>At 22:00 on every day-of-week from Monday through Friday.</td>
      </tr>
  </tbody>
</table>
<p><code>crontab -l</code> lists the already scheduled scripts for a particular user.</p>
]]></content:encoded></item></channel></rss>