{"componentChunkName":"component---src-modules-datocms-post-page-page-tsx","path":"/posts/62","result":{"data":{"post":{"title":"シェルスクリプトの処理境界が鮮明になる「名前付きブロック記法」なるものを考えてみた","author":{"name":"suin","images":{"r32":{"src":"https://www.datocms-assets.com/29850/1591833290-avatar512.jpg?auto=format&fm=png&h=32&mask=ellipse&w=32","srcSet":"https://www.datocms-assets.com/29850/1591833290-avatar512.jpg?auto=format&dpr=1&fm=png&h=32&mask=ellipse&w=32 1x,\nhttps://www.datocms-assets.com/29850/1591833290-avatar512.jpg?auto=format&dpr=1.5&fm=png&h=32&mask=ellipse&w=32 1.5x,\nhttps://www.datocms-assets.com/29850/1591833290-avatar512.jpg?auto=format&dpr=2&fm=png&h=32&mask=ellipse&w=32 2x,\nhttps://www.datocms-assets.com/29850/1591833290-avatar512.jpg?auto=format&dpr=3&fm=png&h=32&mask=ellipse&w=32 3x"},"r48":{"src":"https://www.datocms-assets.com/29850/1591833290-avatar512.jpg?auto=format&fm=png&h=48&mask=ellipse&w=48","srcSet":"https://www.datocms-assets.com/29850/1591833290-avatar512.jpg?auto=format&dpr=1&fm=png&h=48&mask=ellipse&w=48 1x,\nhttps://www.datocms-assets.com/29850/1591833290-avatar512.jpg?auto=format&dpr=1.5&fm=png&h=48&mask=ellipse&w=48 1.5x,\nhttps://www.datocms-assets.com/29850/1591833290-avatar512.jpg?auto=format&dpr=2&fm=png&h=48&mask=ellipse&w=48 2x,\nhttps://www.datocms-assets.com/29850/1591833290-avatar512.jpg?auto=format&dpr=3&fm=png&h=48&mask=ellipse&w=48 3x"}},"bio":"好き: TypeScript, DDD, OOP／#YYTypeScript の主催者／Qiita 4位／株式会社クラフトマンソフトウェア取締役／『実践ドメイン駆動設計』邦訳レビュア／#分報 考案者／Web自動テストShouldBeeを開発"},"date":"2016年3月27日","tags":["bash","shell"],"category":"プログラミング","body":"<p data-sourcepos=\"1:1-3:138\">シェルスクリプトは長くなると処理の境界が不鮮明になりがち。<br>\nコメントで処理の境界を表現する工夫はよく見かけるが、もっと良い方法はないか考えてみた。<br>\n<code>:</code>コマンド、<code>&amp;&amp;</code>演算子、複合コマンド<code>()</code>や<code>{}</code>を組み合わせて書くと、処理の境界線がはっきりする。</p>\n<div class=\"code-block\" data-sourcepos=\"5:1-18:3\">\n<div class=\"code-filename\">\n<i class=\"fa fa-file-code-o\"></i>[Before]コメントで処理の境界を表現したよくあるパタン</div>\n<div class=\"highlight\"><pre class=\"highlight bash\"><code><span class=\"c\"># Install libraries</span>\n<span class=\"nb\">command\ncommand\ncommand</span>\n\n<span class=\"c\"># Build app</span>\n<span class=\"nb\">command\ncommand</span>\n\n<span class=\"c\"># Deploy app to server</span>\n<span class=\"nb\">command\ncommand</span>\n</code></pre></div>\n</div>\n<div class=\"code-block\" data-sourcepos=\"20:1-37:3\">\n<div class=\"code-filename\">\n<i class=\"fa fa-file-code-o\"></i>[After]考えてみた方法で改善してみたパタン</div>\n<div class=\"highlight\"><pre class=\"highlight bash\"><code>: <span class=\"s2\">\"Install libraries\"</span> <span class=\"o\">&amp;&amp;</span> <span class=\"o\">{</span>\n\t<span class=\"nb\">command\n\tcommand\n\tcommand</span>\n<span class=\"o\">}</span>\n\n: <span class=\"s2\">\"Build app\"</span> <span class=\"o\">&amp;&amp;</span> <span class=\"o\">{</span>\n\t<span class=\"nb\">command\n\tcommand</span>\n<span class=\"o\">}</span>\n\n\n: <span class=\"s2\">\"Deploy app to server\"</span> <span class=\"o\">&amp;&amp;</span> <span class=\"o\">{</span>\n\t<span class=\"nb\">command\n\tcommand</span>\n<span class=\"o\">}</span>\n</code></pre></div>\n</div>\n<h1 data-sourcepos=\"39:1-39:65\" id=\"1-0-0\" name=\"1-0-0\">\n<a class=\"anchor\" id=\"シェルスクリプトが長くなるとよく起こる問題\" name=\"%E3%82%B7%E3%82%A7%E3%83%AB%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%97%E3%83%88%E3%81%8C%E9%95%B7%E3%81%8F%E3%81%AA%E3%82%8B%E3%81%A8%E3%82%88%E3%81%8F%E8%B5%B7%E3%81%93%E3%82%8B%E5%95%8F%E9%A1%8C\" href=\"#%E3%82%B7%E3%82%A7%E3%83%AB%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%97%E3%83%88%E3%81%8C%E9%95%B7%E3%81%8F%E3%81%AA%E3%82%8B%E3%81%A8%E3%82%88%E3%81%8F%E8%B5%B7%E3%81%93%E3%82%8B%E5%95%8F%E9%A1%8C\" data-position=\"1-0-0\"><i class=\"fa fa-link\"></i><span class=\"hidden\" data-text=\"シェルスクリプトが長くなるとよく起こる問題\"> &gt; シェルスクリプトが長くなるとよく起こる問題</span></a>シェルスクリプトが長くなるとよく起こる問題</h1>\n<p data-sourcepos=\"41:1-41:294\">シェルスクリプトは作業を自動化するのに便利なツールですが、記述するタスクが増えるにつれて可読性が下がってしまいます。それでも読みやすさを維持するために、様々な工夫をされているのではないでしょうか。</p>\n<p data-sourcepos=\"43:1-43:292\">コメントも工夫の1つです。処理の境界ごとに宣言的なコメントを書いている人も多いとおもいます。たとえば、リリースを自動化するスクリプトなら、おおまかに次のような構成になっているのではないでしょうか？</p>\n<div class=\"code-block\" data-sourcepos=\"45:1-64:3\">\n<div class=\"code-filename\">\n<i class=\"fa fa-file-code-o\"></i>bash</div>\n<div class=\"highlight\"><pre class=\"highlight bash\"><code><span class=\"c\"># Install libraries</span>\n<span class=\"nb\">command\ncommand\ncommand</span>\n\n<span class=\"c\"># Run tests</span>\n<span class=\"nb\">command</span>\n\n<span class=\"c\"># Build app</span>\n<span class=\"nb\">command\ncommand</span>\n\n<span class=\"c\"># Deploy app to server</span>\n<span class=\"nb\">command\ncommand</span>\n\n<span class=\"c\"># Notify result to Slack channel</span>\n<span class=\"nb\">command</span>\n</code></pre></div>\n</div>\n<p data-sourcepos=\"66:1-66:278\">コメントの部分は一定の粒度の処理を宣言していて、コマンドの部分はその具体的な実装になっているパターンです。実装の部分は、if分岐があったりと実際はもっと複雑なコードになっていると思います。</p>\n<p data-sourcepos=\"68:1-68:208\">シェルスクリプトが長くなってくると、<strong>どのコマンドからどのコマンドまでがどの処理なのか一見分かりにくくなる問題</strong>が出てきます。<sup class=\"footnote-ref\"><a href=\"#fn1\" id=\"fnref1\">1</a></sup></p>\n<h1 data-sourcepos=\"73:1-73:32\" id=\"2-0-0\" name=\"2-0-0\">\n<a class=\"anchor\" id=\"名前付きブロック記法\" name=\"%E5%90%8D%E5%89%8D%E4%BB%98%E3%81%8D%E3%83%96%E3%83%AD%E3%83%83%E3%82%AF%E8%A8%98%E6%B3%95\" href=\"#%E5%90%8D%E5%89%8D%E4%BB%98%E3%81%8D%E3%83%96%E3%83%AD%E3%83%83%E3%82%AF%E8%A8%98%E6%B3%95\" data-position=\"2-0-0\"><i class=\"fa fa-link\"></i><span class=\"hidden\" data-text=\"名前付きブロック記法\"> &gt; 名前付きブロック記法</span></a>名前付きブロック記法</h1>\n<p data-sourcepos=\"75:1-75:140\">Bashで処理の境界線をはっきり表現できる<strong>名前付きブロック記法</strong><sup class=\"footnote-ref\"><a href=\"#fn2\" id=\"fnref2\">2</a></sup>というものを考えてみました。</p>\n<p data-sourcepos=\"79:1-79:203\">処理の境界線を表現する方法として真っ先に思いついたのが、<code>{}</code>を使って処理のまとまりを複合コマンドとして表現する方法です。例えば次のように:</p>\n<div class=\"code-block\" data-sourcepos=\"81:1-112:3\">\n<div class=\"code-filename\">\n<i class=\"fa fa-file-code-o\"></i>bash</div>\n<div class=\"highlight\"><pre class=\"highlight bash\"><code><span class=\"c\">#!/bin/bash</span>\n\n<span class=\"c\"># Install libraries</span>\n<span class=\"o\">{</span>\n\t<span class=\"nb\">command\n\tcommand\n\tcommand</span>\n<span class=\"o\">}</span>\n\n<span class=\"c\"># Run tests</span>\n<span class=\"o\">{</span>\n\t<span class=\"nb\">command</span>\n<span class=\"o\">}</span>\n\n<span class=\"c\"># Build app</span>\n<span class=\"o\">{</span>\n\t<span class=\"nb\">command\n\tcommand</span>\n<span class=\"o\">}</span>\n\n<span class=\"c\"># Deploy app to server</span>\n<span class=\"o\">{</span>\n\t<span class=\"nb\">command\n\tcommand</span>\n<span class=\"o\">}</span>\n\n<span class=\"c\"># Notify result to Slack channel</span>\n<span class=\"o\">{</span>\n\t<span class=\"nb\">command</span>\n<span class=\"o\">}</span>\n</code></pre></div>\n</div>\n<p data-sourcepos=\"114:1-114:343\">これだけでも処理がグルーピングされ、だいぶ分かりやすくなります。しかし、これだけだと、コメントとブロックの関係性があまり表現できてない感じがします。そこで、<code>:</code>コマンドと<code>&amp;&amp;</code>で説明文と処理を強く関連付けした形に表現しなおしてみます。</p>\n<div class=\"code-block\" data-sourcepos=\"117:1-143:3\">\n<div class=\"code-filename\">\n<i class=\"fa fa-file-code-o\"></i>bash</div>\n<div class=\"highlight\"><pre class=\"highlight bash\"><code><span class=\"c\">#!/bin/bash</span>\n\n: <span class=\"s2\">\"Install libraries\"</span> <span class=\"o\">&amp;&amp;</span> <span class=\"o\">{</span>\n\t<span class=\"nb\">command\n\tcommand\n\tcommand</span>\n<span class=\"o\">}</span>\n\n: <span class=\"s2\">\"Run tests\"</span> <span class=\"o\">&amp;&amp;</span> <span class=\"o\">{</span>\n\t<span class=\"nb\">command</span>\n<span class=\"o\">}</span>\n\n: <span class=\"s2\">\"Build app\"</span> <span class=\"o\">&amp;&amp;</span> <span class=\"o\">{</span>\n\t<span class=\"nb\">command\n\tcommand</span>\n<span class=\"o\">}</span>\n\n: <span class=\"s2\">\"Deploy app to server\"</span> <span class=\"o\">&amp;&amp;</span> <span class=\"o\">{</span>\n\t<span class=\"nb\">command\n\tcommand</span>\n<span class=\"o\">}</span>\n\n: <span class=\"s2\">\"Notify result to Slack channel\"</span> <span class=\"o\">&amp;&amp;</span> <span class=\"o\">{</span>\n\t<span class=\"nb\">command</span>\n<span class=\"o\">}</span>\n</code></pre></div>\n</div>\n<p data-sourcepos=\"145:1-145:285\">いかがでしょうか？処理の説明と処理の内容が、コメントと比べてなんとなく関連しているように見えませんか？また、シンタクスハイライトで説明文がコメントよりも目立っていて、見出し感も出ていますね。</p>\n<p data-sourcepos=\"147:1-147:138\">処理の境界をコメントで表現する方法と、名前付きブロック記法を一般化すると次のようになります。</p>\n<div class=\"code-block\" data-sourcepos=\"149:1-152:3\">\n<div class=\"code-filename\">\n<i class=\"fa fa-file-code-o\"></i>コメント記法</div>\n<div class=\"highlight\"><pre class=\"highlight bash\"><code><span class=\"c\"># 処理名</span>\n処理...\n</code></pre></div>\n</div>\n<div class=\"code-block\" data-sourcepos=\"154:1-158:3\">\n<div class=\"code-filename\">\n<i class=\"fa fa-file-code-o\"></i>名前付きブロック記法</div>\n<div class=\"highlight\"><pre class=\"highlight bash\"><code>: <span class=\"s2\">\"処理名\"</span> <span class=\"o\">&amp;&amp;</span> <span class=\"o\">{</span>\n  処理...\n<span class=\"o\">}</span>\n</code></pre></div>\n</div>\n<h1 data-sourcepos=\"161:1-161:54\" id=\"3-0-0\" name=\"3-0-0\">\n<a class=\"anchor\" id=\"名前付きブロック記法の6つのメリット\" name=\"%E5%90%8D%E5%89%8D%E4%BB%98%E3%81%8D%E3%83%96%E3%83%AD%E3%83%83%E3%82%AF%E8%A8%98%E6%B3%95%E3%81%AE6%E3%81%A4%E3%81%AE%E3%83%A1%E3%83%AA%E3%83%83%E3%83%88\" href=\"#%E5%90%8D%E5%89%8D%E4%BB%98%E3%81%8D%E3%83%96%E3%83%AD%E3%83%83%E3%82%AF%E8%A8%98%E6%B3%95%E3%81%AE6%E3%81%A4%E3%81%AE%E3%83%A1%E3%83%AA%E3%83%83%E3%83%88\" data-position=\"3-0-0\"><i class=\"fa fa-link\"></i><span class=\"hidden\" data-text=\"名前付きブロック記法の6つのメリット\"> &gt; 名前付きブロック記法の6つのメリット</span></a>名前付きブロック記法の6つのメリット</h1>\n<p data-sourcepos=\"163:1-163:150\">コメントで処理の境界線を表現するのと比べて、名前付きブロック記法には次のメリットがあると思いました。</p>\n<ol data-sourcepos=\"165:1-171:0\">\n<li data-sourcepos=\"165:1-165:42\">処理の境界線がはっきりする</li>\n<li data-sourcepos=\"166:1-166:21\">ネストできる</li>\n<li data-sourcepos=\"167:1-167:34\">Bash標準の機能で書ける</li>\n<li data-sourcepos=\"168:1-168:27\">デバッグしやすい</li>\n<li data-sourcepos=\"169:1-169:36\">エディタで折りたためる</li>\n<li data-sourcepos=\"170:1-171:0\">一時的に処理を無効にするのも容易</li>\n</ol>\n<h2 data-sourcepos=\"172:1-172:57\" id=\"3-1-0\" name=\"3-1-0\">\n<a class=\"anchor\" id=\"メリット1: 処理の境界線がはっきりする\" name=\"%E3%83%A1%E3%83%AA%E3%83%83%E3%83%881:%20%E5%87%A6%E7%90%86%E3%81%AE%E5%A2%83%E7%95%8C%E7%B7%9A%E3%81%8C%E3%81%AF%E3%81%A3%E3%81%8D%E3%82%8A%E3%81%99%E3%82%8B\" href=\"#%E3%83%A1%E3%83%AA%E3%83%83%E3%83%881:%20%E5%87%A6%E7%90%86%E3%81%AE%E5%A2%83%E7%95%8C%E7%B7%9A%E3%81%8C%E3%81%AF%E3%81%A3%E3%81%8D%E3%82%8A%E3%81%99%E3%82%8B\" data-position=\"3-1-0\"><i class=\"fa fa-link\"></i><span class=\"hidden\" data-text=\"メリット1__colon__ 処理の境界線がはっきりする\"> &gt; メリット1__colon__ 処理の境界線がはっきりする</span></a>メリット1: 処理の境界線がはっきりする</h2>\n<p data-sourcepos=\"174:1-174:165\">ブレースで処理がグルーピングされ、インデントもつくため、コードを眺めたときに処理の境界を把握しやすくなります。</p>\n<h2 data-sourcepos=\"176:1-176:36\" id=\"3-2-0\" name=\"3-2-0\">\n<a class=\"anchor\" id=\"メリット2: ネストできる\" name=\"%E3%83%A1%E3%83%AA%E3%83%83%E3%83%882:%20%E3%83%8D%E3%82%B9%E3%83%88%E3%81%A7%E3%81%8D%E3%82%8B\" href=\"#%E3%83%A1%E3%83%AA%E3%83%83%E3%83%882:%20%E3%83%8D%E3%82%B9%E3%83%88%E3%81%A7%E3%81%8D%E3%82%8B\" data-position=\"3-2-0\"><i class=\"fa fa-link\"></i><span class=\"hidden\" data-text=\"メリット2__colon__ ネストできる\"> &gt; メリット2__colon__ ネストできる</span></a>メリット2: ネストできる</h2>\n<p data-sourcepos=\"178:1-178:126\">複合コマンドはネストすることができるため、サブ処理をネストで表現することができます。</p>\n<div class=\"code-block\" data-sourcepos=\"180:1-195:3\">\n<div class=\"code-filename\">\n<i class=\"fa fa-file-code-o\"></i>bash</div>\n<div class=\"highlight\"><pre class=\"highlight bash\"><code>: <span class=\"s2\">\"setup database\"</span> <span class=\"o\">&amp;&amp;</span> <span class=\"o\">{</span>\n\t: <span class=\"s2\">\"create database\"</span> <span class=\"o\">&amp;&amp;</span> <span class=\"o\">{</span>\n\t\t<span class=\"nb\">command\n\t\tcommand</span>\n\t<span class=\"o\">}</span>\n\t: <span class=\"s2\">\"migrate database schema\"</span> <span class=\"o\">&amp;&amp;</span> <span class=\"o\">{</span>\n\t\t<span class=\"nb\">command\n\t\tcommand</span>\n\t<span class=\"o\">}</span>\n\t: <span class=\"s2\">\"store dummy data\"</span> <span class=\"o\">&amp;&amp;</span> <span class=\"o\">{</span>\n\t\t<span class=\"nb\">command\n\t\tcommand</span>\n\t<span class=\"o\">}</span>\n<span class=\"o\">}</span>\n</code></pre></div>\n</div>\n<h2 data-sourcepos=\"197:1-197:49\" id=\"3-3-0\" name=\"3-3-0\">\n<a class=\"anchor\" id=\"メリット3: Bash標準の機能で書ける\" name=\"%E3%83%A1%E3%83%AA%E3%83%83%E3%83%883:%20Bash%E6%A8%99%E6%BA%96%E3%81%AE%E6%A9%9F%E8%83%BD%E3%81%A7%E6%9B%B8%E3%81%91%E3%82%8B\" href=\"#%E3%83%A1%E3%83%AA%E3%83%83%E3%83%883:%20Bash%E6%A8%99%E6%BA%96%E3%81%AE%E6%A9%9F%E8%83%BD%E3%81%A7%E6%9B%B8%E3%81%91%E3%82%8B\" data-position=\"3-3-0\"><i class=\"fa fa-link\"></i><span class=\"hidden\" data-text=\"メリット3__colon__ Bash標準の機能で書ける\"> &gt; メリット3__colon__ Bash標準の機能で書ける</span></a>メリット3: Bash標準の機能で書ける</h2>\n<p data-sourcepos=\"199:1-199:193\">記法の構成要素については後述しますが、使用するコードはすべてBashの標準機能です。必要な外部ライブラリなしに記述できるのが特徴です。</p>\n<h2 data-sourcepos=\"201:1-201:42\" id=\"3-4-0\" name=\"3-4-0\">\n<a class=\"anchor\" id=\"メリット4: デバッグしやすい\" name=\"%E3%83%A1%E3%83%AA%E3%83%83%E3%83%884:%20%E3%83%87%E3%83%90%E3%83%83%E3%82%B0%E3%81%97%E3%82%84%E3%81%99%E3%81%84\" href=\"#%E3%83%A1%E3%83%AA%E3%83%83%E3%83%884:%20%E3%83%87%E3%83%90%E3%83%83%E3%82%B0%E3%81%97%E3%82%84%E3%81%99%E3%81%84\" data-position=\"3-4-0\"><i class=\"fa fa-link\"></i><span class=\"hidden\" data-text=\"メリット4__colon__ デバッグしやすい\"> &gt; メリット4__colon__ デバッグしやすい</span></a>メリット4: デバッグしやすい</h2>\n<p data-sourcepos=\"203:1-204:221\">Bashは<code>-x</code>オプションで実行コマンドを出力することができます。<br>\nコメントは<code>-x</code>オプションでデバッグすることはできませんが、<code>:</code>はコマンドの一種なので、<code>-x</code>オプションで処理名を表示することができデバッグがはかどります。</p>\n<div class=\"code-block\" data-sourcepos=\"206:1-234:3\">\n<div class=\"code-filename\">\n<i class=\"fa fa-file-code-o\"></i>bash</div>\n<div class=\"highlight\"><pre class=\"highlight bash\"><code><span class=\"c\">#!/bin/bash</span>\n\n<span class=\"nb\">set</span> <span class=\"nt\">-x</span> <span class=\"c\"># デバッグオプション</span>\n\n: <span class=\"s2\">\"Install libraries\"</span> <span class=\"o\">&amp;&amp;</span> <span class=\"o\">{</span>\n    <span class=\"nb\">command\n    command\n    command</span>\n<span class=\"o\">}</span>\n\n: <span class=\"s2\">\"Run tests\"</span> <span class=\"o\">&amp;&amp;</span> <span class=\"o\">{</span>\n    <span class=\"nb\">command</span>\n<span class=\"o\">}</span>\n\n: <span class=\"s2\">\"Build app\"</span> <span class=\"o\">&amp;&amp;</span> <span class=\"o\">{</span>\n    <span class=\"nb\">command\n    command</span>\n<span class=\"o\">}</span>\n\n: <span class=\"s2\">\"Deploy app to server\"</span> <span class=\"o\">&amp;&amp;</span> <span class=\"o\">{</span>\n    <span class=\"nb\">command\n    command</span>\n<span class=\"o\">}</span>\n\n: <span class=\"s2\">\"Notify result to Slack channel\"</span> <span class=\"o\">&amp;&amp;</span> <span class=\"o\">{</span>\n    <span class=\"nb\">command</span>\n<span class=\"o\">}</span>\n</code></pre></div>\n</div>\n<div class=\"code-block\" data-sourcepos=\"236:1-251:3\">\n<div class=\"code-filename\">\n<i class=\"fa fa-file-code-o\"></i>出力結果</div>\n<div class=\"highlight\"><pre class=\"highlight text\"><code>+ : 'Install libraries'\n+ command\n+ command\n+ command\n+ : 'Run tests'\n+ command\n+ : 'Build app'\n+ command\n+ command\n+ : 'Deploy app to server'\n+ command\n+ command\n+ : 'Notify result to Slack channel'\n+ command\n</code></pre></div>\n</div>\n<h2 data-sourcepos=\"253:1-253:51\" id=\"3-5-0\" name=\"3-5-0\">\n<a class=\"anchor\" id=\"メリット5: エディタで折りたためる\" name=\"%E3%83%A1%E3%83%AA%E3%83%83%E3%83%885:%20%E3%82%A8%E3%83%87%E3%82%A3%E3%82%BF%E3%81%A7%E6%8A%98%E3%82%8A%E3%81%9F%E3%81%9F%E3%82%81%E3%82%8B\" href=\"#%E3%83%A1%E3%83%AA%E3%83%83%E3%83%885:%20%E3%82%A8%E3%83%87%E3%82%A3%E3%82%BF%E3%81%A7%E6%8A%98%E3%82%8A%E3%81%9F%E3%81%9F%E3%82%81%E3%82%8B\" data-position=\"3-5-0\"><i class=\"fa fa-link\"></i><span class=\"hidden\" data-text=\"メリット5__colon__ エディタで折りたためる\"> &gt; メリット5__colon__ エディタで折りたためる</span></a>メリット5: エディタで折りたためる</h2>\n<p data-sourcepos=\"255:1-255:112\">エディタで折りたたみ機能を使う人にとっては1つのメリットになるかと思います。</p>\n<figure><a href=\"https://c16e-esa-io-public-files.s3-ap-northeast-1.amazonaws.com/uploads/production/attachments/15637/2020/05/28/18740/5aa2ee37-d041-40bf-83eb-dd1f45290eab.gif\" target=\"_blank\" rel=\"noopener noreferrer\"><img width=\"378\" alt=\"01.gif (30.3 kB)\" src=\"https://c16e-esa-io-public-files.s3-ap-northeast-1.amazonaws.com/uploads/production/attachments/15637/2020/05/28/18740/5aa2ee37-d041-40bf-83eb-dd1f45290eab.gif\"></a><figcaption>Atomエディタでの折りたたみ</figcaption></figure>\n<h2 data-sourcepos=\"259:1-259:66\" id=\"3-6-0\" name=\"3-6-0\">\n<a class=\"anchor\" id=\"メリット6: 一時的に処理を無効にするのも容易\" name=\"%E3%83%A1%E3%83%AA%E3%83%83%E3%83%886:%20%E4%B8%80%E6%99%82%E7%9A%84%E3%81%AB%E5%87%A6%E7%90%86%E3%82%92%E7%84%A1%E5%8A%B9%E3%81%AB%E3%81%99%E3%82%8B%E3%81%AE%E3%82%82%E5%AE%B9%E6%98%93\" href=\"#%E3%83%A1%E3%83%AA%E3%83%83%E3%83%886:%20%E4%B8%80%E6%99%82%E7%9A%84%E3%81%AB%E5%87%A6%E7%90%86%E3%82%92%E7%84%A1%E5%8A%B9%E3%81%AB%E3%81%99%E3%82%8B%E3%81%AE%E3%82%82%E5%AE%B9%E6%98%93\" data-position=\"3-6-0\"><i class=\"fa fa-link\"></i><span class=\"hidden\" data-text=\"メリット6__colon__ 一時的に処理を無効にするのも容易\"> &gt; メリット6__colon__ 一時的に処理を無効にするのも容易</span></a>メリット6: 一時的に処理を無効にするのも容易</h2>\n<p data-sourcepos=\"261:1-261:110\">処理を一時的に無効にしたい場合は、<code>&amp;&amp;</code>を<code>||</code>に置き換えるだけで対応できます。</p>\n<div class=\"code-block\" data-sourcepos=\"263:1-271:3\">\n<div class=\"code-filename\">\n<i class=\"fa fa-file-code-o\"></i>bash</div>\n<div class=\"highlight\"><pre class=\"highlight bash\"><code><span class=\"c\">#!/bin/bash -eux</span>\n\n: <span class=\"s2\">\"Install libraries\"</span> <span class=\"o\">||</span> <span class=\"o\">{</span>\n    <span class=\"nb\">command\n    command\n    command</span>\n<span class=\"o\">}</span>\n</code></pre></div>\n</div>\n<h1 data-sourcepos=\"273:1-273:56\" id=\"4-0-0\" name=\"4-0-0\">\n<a class=\"anchor\" id=\"名前付きブロック記法の構成要素の説明\" name=\"%E5%90%8D%E5%89%8D%E4%BB%98%E3%81%8D%E3%83%96%E3%83%AD%E3%83%83%E3%82%AF%E8%A8%98%E6%B3%95%E3%81%AE%E6%A7%8B%E6%88%90%E8%A6%81%E7%B4%A0%E3%81%AE%E8%AA%AC%E6%98%8E\" href=\"#%E5%90%8D%E5%89%8D%E4%BB%98%E3%81%8D%E3%83%96%E3%83%AD%E3%83%83%E3%82%AF%E8%A8%98%E6%B3%95%E3%81%AE%E6%A7%8B%E6%88%90%E8%A6%81%E7%B4%A0%E3%81%AE%E8%AA%AC%E6%98%8E\" data-position=\"4-0-0\"><i class=\"fa fa-link\"></i><span class=\"hidden\" data-text=\"名前付きブロック記法の構成要素の説明\"> &gt; 名前付きブロック記法の構成要素の説明</span></a>名前付きブロック記法の構成要素の説明</h1>\n<p data-sourcepos=\"275:1-275:187\">名前付きブロック記法の「<code>:</code>や<code>{}</code>って何だろう？」と疑問を持たれた方もいると思うので、構成要素についても簡単に説明しておきます。</p>\n<h2 data-sourcepos=\"277:1-277:18\" id=\"4-1-0\" name=\"4-1-0\">\n<a class=\"anchor\" id=\":コマンド\" name=\":%E3%82%B3%E3%83%9E%E3%83%B3%E3%83%89\" href=\"#:%E3%82%B3%E3%83%9E%E3%83%B3%E3%83%89\" data-position=\"4-1-0\"><i class=\"fa fa-link\"></i><span class=\"hidden\" data-text=\"__colon__コマンド\"> &gt; __colon__コマンド</span></a><code>:</code>コマンド</h2>\n<p data-sourcepos=\"279:1-279:110\"><code>:</code>コマンドはBashでは何もしないコマンドです。そして、常にsuccessで終わります。</p>\n<div class=\"code-block\" data-sourcepos=\"281:1-283:3\">\n<div class=\"code-filename\">\n<i class=\"fa fa-file-code-o\"></i>bash</div>\n<div class=\"highlight\"><pre class=\"highlight bash\"><code>: <span class=\"s2\">\"do nothing\"</span>\n</code></pre></div>\n</div>\n<p data-sourcepos=\"285:1-285:144\">コメントとの違いは実行されるコマンドという点です。なので、サブシェルや変数を扱うこともできます。</p>\n<div class=\"code-block\" data-sourcepos=\"287:1-291:3\">\n<div class=\"code-filename\">\n<i class=\"fa fa-file-code-o\"></i>bash</div>\n<div class=\"highlight\"><pre class=\"highlight bash\"><code><span class=\"c\">#!/bin/bash</span>\n<span class=\"nb\">set</span> <span class=\"nt\">-x</span>\n: <span class=\"s2\">\"current directory is </span><span class=\"nv\">$PWD</span><span class=\"s2\">\"</span>\n</code></pre></div>\n</div>\n<div class=\"code-block\" data-sourcepos=\"293:1-295:3\">\n<div class=\"code-filename\">\n<i class=\"fa fa-file-code-o\"></i>出力結果</div>\n<div class=\"highlight\"><pre class=\"highlight text\"><code>+ : 'current directory is /Users/suin/Desktop'\n</code></pre></div>\n</div>\n<p data-sourcepos=\"297:1-297:99\">名前付きブロック記法では、<code>:</code>コマンドを説明文として活用しています。</p>\n<h2 data-sourcepos=\"299:1-299:16\" id=\"4-2-0\" name=\"4-2-0\">\n<a class=\"anchor\" id=\"&amp;amp;&amp;amp;演算子\" name=\"&amp;amp;&amp;amp;%E6%BC%94%E7%AE%97%E5%AD%90\" href=\"#&amp;amp;&amp;amp;%E6%BC%94%E7%AE%97%E5%AD%90\" data-position=\"4-2-0\"><i class=\"fa fa-link\"></i><span class=\"hidden\" data-text=\"&amp;amp;&amp;amp;演算子\"> &gt; &amp;&amp;演算子</span></a><code>&amp;&amp;</code>演算子</h2>\n<p data-sourcepos=\"301:1-301:107\">&amp;&amp;演算子は前のコマンドが成功した場合、次のコマンドを実行する演算子です。</p>\n<div class=\"code-block\" data-sourcepos=\"303:1-307:3\">\n<div class=\"code-filename\">\n<i class=\"fa fa-file-code-o\"></i>bash</div>\n<div class=\"highlight\"><pre class=\"highlight bash\"><code><span class=\"c\">#!/bin/bash</span>\n<span class=\"nb\">true</span> <span class=\"o\">&amp;&amp;</span> <span class=\"nb\">echo </span>1  <span class=\"c\"># 1は出力される</span>\n<span class=\"nb\">false</span> <span class=\"o\">&amp;&amp;</span> <span class=\"nb\">echo </span>2 <span class=\"c\"># 2は出力されない</span>\n</code></pre></div>\n</div>\n<p data-sourcepos=\"309:1-309:134\"><code>:</code>コマンドは常にsuccessで終わるので、<code>&amp;&amp;</code>演算子以降のコマンドは必ず実行されるというわけです。</p>\n<h2 data-sourcepos=\"311:1-311:25\" id=\"4-3-0\" name=\"4-3-0\">\n<a class=\"anchor\" id=\"複合コマンド{}\" name=\"%E8%A4%87%E5%90%88%E3%82%B3%E3%83%9E%E3%83%B3%E3%83%89%7B%7D\" href=\"#%E8%A4%87%E5%90%88%E3%82%B3%E3%83%9E%E3%83%B3%E3%83%89%7B%7D\" data-position=\"4-3-0\"><i class=\"fa fa-link\"></i><span class=\"hidden\" data-text=\"複合コマンド{}\"> &gt; 複合コマンド{}</span></a>複合コマンド<code>{}</code>\n</h2>\n<p data-sourcepos=\"313:1-313:112\">Bashでは<code>{}</code>や<code>()</code>で複数のコマンドを1つのコマンドとして複合することができます。</p>\n<div class=\"code-block\" data-sourcepos=\"315:1-325:3\">\n<div class=\"code-filename\">\n<i class=\"fa fa-file-code-o\"></i>bash</div>\n<div class=\"highlight\"><pre class=\"highlight bash\"><code><span class=\"c\">#!/bin/bash</span>\n\n<span class=\"o\">{</span>\n\t<span class=\"nb\">echo </span>1\n\t<span class=\"nb\">echo </span>2\n\t<span class=\"nb\">echo </span>3\n<span class=\"o\">}</span> <span class=\"o\">&gt;</span> /tmp/output\n\n<span class=\"nb\">cat</span> /tmp/output\n</code></pre></div>\n</div>\n<div class=\"code-block\" data-sourcepos=\"327:1-331:3\">\n<div class=\"code-filename\">\n<i class=\"fa fa-file-code-o\"></i>実行結果</div>\n<div class=\"highlight\"><pre class=\"highlight text\"><code>1\n2\n3\n</code></pre></div>\n</div>\n<p data-sourcepos=\"333:1-333:95\"><code>{}</code>は現在のシェルで、<code>()</code>はサブシェルで実行される違いがあります。</p>\n<div class=\"code-block\" data-sourcepos=\"335:1-349:3\">\n<div class=\"code-filename\">\n<i class=\"fa fa-file-code-o\"></i>bash</div>\n<div class=\"highlight\"><pre class=\"highlight bash\"><code><span class=\"c\">#!/bin/bash</span>\n\n<span class=\"nv\">foo</span><span class=\"o\">=</span>1\n<span class=\"o\">(</span>\n\t<span class=\"nv\">foo</span><span class=\"o\">=</span>2\n\t<span class=\"nb\">echo</span> <span class=\"nv\">$foo</span> <span class=\"c\"># 2が出力される。サブシェル内なので親シェルのfooは書き換えない</span>\n<span class=\"o\">)</span>\n<span class=\"nb\">echo</span> <span class=\"nv\">$foo</span> <span class=\"c\"># 1が出力される</span>\n\n<span class=\"o\">{</span>\n\t<span class=\"nv\">foo</span><span class=\"o\">=</span>2 <span class=\"c\"># 現行シェルで実行されるのでfooが書き換わる</span>\n<span class=\"o\">}</span>\n<span class=\"nb\">echo</span> <span class=\"nv\">$foo</span> <span class=\"c\"># 2</span>\n</code></pre></div>\n</div>\n<h1 data-sourcepos=\"351:1-351:11\" id=\"5-0-0\" name=\"5-0-0\">\n<a class=\"anchor\" id=\"まとめ\" name=\"%E3%81%BE%E3%81%A8%E3%82%81\" href=\"#%E3%81%BE%E3%81%A8%E3%82%81\" data-position=\"5-0-0\"><i class=\"fa fa-link\"></i><span class=\"hidden\" data-text=\"まとめ\"> &gt; まとめ</span></a>まとめ</h1>\n<ul data-sourcepos=\"353:1-355:140\">\n<li data-sourcepos=\"353:1-353:89\">シェルスクリプトは長くなると処理の境界が不鮮明になりがち。</li>\n<li data-sourcepos=\"354:1-354:131\">コメントで処理の境界を表現する工夫はよく見かけるが、もっと良い方法はないか考えてみた。</li>\n<li data-sourcepos=\"355:1-355:140\">\n<code>:</code>コマンド、<code>&amp;&amp;</code>演算子、複合コマンド<code>()</code>や<code>{}</code>を組み合わせて書くと、処理の境界線がはっきりする。</li>\n</ul>\n<section class=\"footnotes\">\n<ol>\n<li id=\"fn1\">\n<p data-sourcepos=\"70:24-70:357\">シェルスクリプトがあまりにも長い場合は、関数やファイルを分割することで、処理を分ける方法も考えられます。ここでは、1ファイル内での処理の境界線を明確にする方法のみを考えるため、関数やファイル分割する方法については割愛します。 <a href=\"#fnref1\" class=\"footnote-backref\">↩</a></p>\n</li>\n<li id=\"fn2\">\n<p data-sourcepos=\"77:12-77:197\">この呼称は僕が考えたもので、もしかしたら既に流通している呼称があるかもしれません。ご存知の方はコメントいただければ幸いです。 <a href=\"#fnref2\" class=\"footnote-backref\">↩</a></p>\n</li>\n</ol>\n</section>\n"}},"pageContext":{"id":"DatoCmsPost-5142999-ja","description":"シェルスクリプトは長くなると処理の境界が不鮮明になりがち。 コメントで処理の境界を表現する工夫はよく見かけるが、もっと良い方法はないか考えてみた。 :コマンド、&&演算子、複合コマンド()や{}を組み合わせて書くと、処理の境界線がはっきりする。 シェルスクリプトが長くなるとよく起こる問題 シェルスクリプトは作業を自動化するのに便利なツールですが、記述するタスクが増えるにつれて可読性が下がってしまいます。それでも読みやすさを維持するために、様々な工夫をされているのではないでしょうか。 コメントも工夫の1つです。処理の境界ごとに宣言的なコメントを書いている人も多いとおもいます。たとえば、リリースを","toc":[{"tag":"h1","depth":1,"href":"#%E3%82%B7%E3%82%A7%E3%83%AB%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%97%E3%83%88%E3%81%8C%E9%95%B7%E3%81%8F%E3%81%AA%E3%82%8B%E3%81%A8%E3%82%88%E3%81%8F%E8%B5%B7%E3%81%93%E3%82%8B%E5%95%8F%E9%A1%8C","text":"シェルスクリプトが長くなるとよく起こる問題","html":"シェルスクリプトが長くなるとよく起こる問題"},{"tag":"h1","depth":1,"href":"#%E5%90%8D%E5%89%8D%E4%BB%98%E3%81%8D%E3%83%96%E3%83%AD%E3%83%83%E3%82%AF%E8%A8%98%E6%B3%95","text":"名前付きブロック記法","html":"名前付きブロック記法"},{"tag":"h1","depth":1,"href":"#%E5%90%8D%E5%89%8D%E4%BB%98%E3%81%8D%E3%83%96%E3%83%AD%E3%83%83%E3%82%AF%E8%A8%98%E6%B3%95%E3%81%AE6%E3%81%A4%E3%81%AE%E3%83%A1%E3%83%AA%E3%83%83%E3%83%88","text":"名前付きブロック記法の6つのメリット","html":"名前付きブロック記法の6つのメリット"},{"tag":"h2","depth":2,"href":"#%E3%83%A1%E3%83%AA%E3%83%83%E3%83%881:%20%E5%87%A6%E7%90%86%E3%81%AE%E5%A2%83%E7%95%8C%E7%B7%9A%E3%81%8C%E3%81%AF%E3%81%A3%E3%81%8D%E3%82%8A%E3%81%99%E3%82%8B","text":"メリット1: 処理の境界線がはっきりする","html":"メリット1: 処理の境界線がはっきりする"},{"tag":"h2","depth":2,"href":"#%E3%83%A1%E3%83%AA%E3%83%83%E3%83%882:%20%E3%83%8D%E3%82%B9%E3%83%88%E3%81%A7%E3%81%8D%E3%82%8B","text":"メリット2: ネストできる","html":"メリット2: ネストできる"},{"tag":"h2","depth":2,"href":"#%E3%83%A1%E3%83%AA%E3%83%83%E3%83%883:%20Bash%E6%A8%99%E6%BA%96%E3%81%AE%E6%A9%9F%E8%83%BD%E3%81%A7%E6%9B%B8%E3%81%91%E3%82%8B","text":"メリット3: Bash標準の機能で書ける","html":"メリット3: Bash標準の機能で書ける"},{"tag":"h2","depth":2,"href":"#%E3%83%A1%E3%83%AA%E3%83%83%E3%83%884:%20%E3%83%87%E3%83%90%E3%83%83%E3%82%B0%E3%81%97%E3%82%84%E3%81%99%E3%81%84","text":"メリット4: デバッグしやすい","html":"メリット4: デバッグしやすい"},{"tag":"h2","depth":2,"href":"#%E3%83%A1%E3%83%AA%E3%83%83%E3%83%885:%20%E3%82%A8%E3%83%87%E3%82%A3%E3%82%BF%E3%81%A7%E6%8A%98%E3%82%8A%E3%81%9F%E3%81%9F%E3%82%81%E3%82%8B","text":"メリット5: エディタで折りたためる","html":"メリット5: エディタで折りたためる"},{"tag":"h2","depth":2,"href":"#%E3%83%A1%E3%83%AA%E3%83%83%E3%83%886:%20%E4%B8%80%E6%99%82%E7%9A%84%E3%81%AB%E5%87%A6%E7%90%86%E3%82%92%E7%84%A1%E5%8A%B9%E3%81%AB%E3%81%99%E3%82%8B%E3%81%AE%E3%82%82%E5%AE%B9%E6%98%93","text":"メリット6: 一時的に処理を無効にするのも容易","html":"メリット6: 一時的に処理を無効にするのも容易"},{"tag":"h1","depth":1,"href":"#%E5%90%8D%E5%89%8D%E4%BB%98%E3%81%8D%E3%83%96%E3%83%AD%E3%83%83%E3%82%AF%E8%A8%98%E6%B3%95%E3%81%AE%E6%A7%8B%E6%88%90%E8%A6%81%E7%B4%A0%E3%81%AE%E8%AA%AC%E6%98%8E","text":"名前付きブロック記法の構成要素の説明","html":"名前付きブロック記法の構成要素の説明"},{"tag":"h2","depth":2,"href":"#:%E3%82%B3%E3%83%9E%E3%83%B3%E3%83%89","text":":コマンド","html":"<code>:</code>コマンド"},{"tag":"h2","depth":2,"href":"#&amp;&amp;%E6%BC%94%E7%AE%97%E5%AD%90","text":"&&演算子","html":"<code>&amp;&amp;</code>演算子"},{"tag":"h2","depth":2,"href":"#%E8%A4%87%E5%90%88%E3%82%B3%E3%83%9E%E3%83%B3%E3%83%89%7B%7D","text":"複合コマンド{}","html":"複合コマンド<code>{}</code>"},{"tag":"h1","depth":1,"href":"#%E3%81%BE%E3%81%A8%E3%82%81","text":"まとめ","html":"まとめ"}],"ogpImageUrl":"https://www.datocms-assets.com/29850/1593190022-pastedimage20200627146.png?fm=png&mark64=aHR0cHM6Ly93d3cuZGF0b2Ntcy1hc3NldHMuY29tLzI5ODUwLzE1OTMxNTQ2MzYtdHJhbnNwYXJlbnQtcGl4ZWwucG5nP3c9NDAwJmg9NjQmZml0PWNyb3AmYmxlbmQ2ND1hSFIwY0hNNkx5OTNkM2N1WkdGMGIyTnRjeTFoYzNObGRITXVZMjl0THpJNU9EVXdMekUxT1RFNE16TXlPVEF0WVhaaGRHRnlOVEV5TG1wd1p6OXRZWE5yUFdWc2JHbHdjMlVtWm0wOWNHNW5KbmM5TWpVMkptZzlNalUyJmJsZW5kLWg9NjQmYmxlbmQteD0wJmJsZW5kLXk9MCZibGVuZC1tb2RlPW5vcm1hbCZtYXJrNjQ9YUhSMGNITTZMeTloYzNObGRITXVhVzFuYVhndWJtVjBMMzUwWlhoMFAzUjRkQzFoYkdsbmJqMXRhV1JrYkdVbE1rTnNaV1owSm5SNGRDMW1iMjUwUFhOaGJuTXRjMlZ5YVdZbE1rTmliMnhrSm5SNGRDMWpiMnh2Y2oweU1qRTRNVFltZEhoME5qUTlZek5XY0dKbkpuUjRkQzF6YVhwbFBUTXdKbWc5TmpRJm1hcmsteD02NCZtYXJrLWFsaWduPW1pZGRsZSUyQ2xlZnQ&mark-align=bottom%2Cleft&mark-x=100&mark-y=496&blend64=aHR0cHM6Ly93d3cuZGF0b2Ntcy1hc3NldHMuY29tLzI5ODUwLzE1OTMxNTQ2MzYtdHJhbnNwYXJlbnQtcGl4ZWwucG5nP3c9MTIwMCZoPTYzMCZmaXQ9Y3JvcCZtYXJrNjQ9YUhSMGNITTZMeTkzZDNjdVpHRjBiMk50Y3kxaGMzTmxkSE11WTI5dEx6STVPRFV3THpFMU9UTXhOVEE1TkRBdFkzSmhablJ6YldGdUxUQXhMbkJ1WncmbWFyay1hbGlnbj10b3AlMkNjZW50ZXImbWFyay13PTI1MCZtYXJrLXk9ODAmYmxlbmQ2ND1hSFIwY0hNNkx5OWhjM05sZEhNdWFXMW5hWGd1Ym1WMEwzNTBaWGgwUDNSNGRDMWhiR2xuYmoxdGFXUmtiR1VsTWtOalpXNTBaWEltZEhoMExXWnZiblE5YzJGdWN5MXpaWEpwWmlVeVEySnZiR1FtZEhoMExYQmhaRDB4TURBbWRIaDBMV052Ykc5eVBUSXlNVGd4TmlaMGVIUTJORDAwTkVzek5EUkxialEwVDNJME5FczFORFJMZGpRMFQzRTBORTlZTkRSUFNUUTBSM1UxV1dWdE5UVkRSelZoUzBRMU5WZE5ORFJIVFRaaE5uVTFjR2xQTkRSSGNqUTBSM0UwTkV0TU5EUkRUVFZhUTA0MVdXMU9OVXgxV1RRMFIwNDBORTlYTkRSUGREUTBUMFEwTkV0Mk5rdHBXVFZ5VDFZME5FTk9ORFJIY1RRMFMwdzBORXRETkRSSGRUUTBTMU0yU1VORU5EUkhTVFEwUjIwME5FZGZORFJIWmlaMGVIUXRjMmw2WlQwMU5TWjNQVEV5TURBbWFEMDJNekEmYmxlbmQtbW9kZT1ub3JtYWw&blend-mode=normal"}}}