Upgrade to Pro — share decks privately, control downloads, hide ads and more …

2026-03-27 #terminalnight 変数展開とコマンド展開でターミナル作業をス...

2026-03-27 #terminalnight 変数展開とコマンド展開でターミナル作業をスマートにする方法

怠惰な人がコマンドライン操作を楽をするためのテクニック

[Terminal Night #2 - connpass](https://kichijojipm.connpass.com/event/382650/)

Avatar for SUZUKI Masashi

SUZUKI Masashi

March 27, 2026
Tweet

More Decks by SUZUKI Masashi

Other Decks in Programming

Transcript

  1. おまえだれよ 名前: すずきまさし/x:@masasuz/masasuzu 所属: 株式会社スリーシェイク シニアアーキテクト クラウドインフラ何でも屋さん すきなもの: AWS, Google

    Cloud, Terraform 2024-2025 AWS Community Builder Cloud Operations 2025 Japan All AWS Certifications Engineers Google Cloud Partner Top Engineer 2026 2
  2. 一番好きなターミナルはVS Code備え付けのターミナルです 昔はsshでリモートサーバにログインして、そこで全ての作業をしていました 昔はzshとかtmuxとかvimの設定をいろいろやってましたが、 、 、 今は基本的にローカルのVS Codeでだいたいなんとかしてます ウィンドウ1枚で完結したいので、VS Code備え付けを使ってます

    今日の発表者で一番意識低いかもしれないです 他の方の今日の資料を見返して意識上げていきます 普段使いのshellはzsh 今回のスライドの例は基本的にbashです zshとの差異は補足します 今回のスライドはマークダウンで記述してmarpで出力しています 3
  3. 今日紹介する3つの展開+α 展開 用途 覚える構文 ブレース展開 パスの共通部分をまとめる {a,b} , {1..10} 変数展開

    値を再利用・文字列操作 ${var} , ${var%pat} コマンド展開 コマンド結果をその場で使う $(command) プロセス置換 コマンド出力をファイルとして扱う <(command) → これらを使えばコピペを減らせるようになります 7
  4. ブレース展開 — パスを1回だけ書く Before: cp /etc/nginx/nginx.conf /etc/nginx/nginx.conf.bak After: cp /etc/nginx/nginx.conf{,.bak}

    パスを1回しか書かないからタイポで別ファイルを上書きする事故が起きない 9
  5. ブレース展開の活用例 # 拡張子の変更 mv report.{txt,md} # ディレクトリの一括作成 mkdir -p project/{src,bin,lib,test}

    # 設定ファイルの比較 diff /etc/nginx/sites-{available,enabled}/mysite.conf # 連番のログファイルを一括検索 cat app-202603{15..17}.log | grep ERROR 10
  6. 変数展開 — 値を変数に入れて再利用 Before: 環境名を手動で書き換え(書き換え忘れの危険) aws s3 sync ./dist s3://myapp-staging-assets/

    # → production にデプロイ(コピペして書き換え) aws s3 sync ./dist s3://myapp-production-assets/ After: 変数で1箇所管理 ENV=staging # ここだけ変えれば全て切り替わる BUCKET="myapp-${ENV}-assets" aws s3 sync ./dist "s3://${BUCKET}/" ENV=production BUCKET="myapp-${ENV}-assets" aws s3 sync ./dist "s3://${BUCKET}/" 12
  7. 変数展開 — コマンド結果を変数に格納 コマンド展開と組み合わせて、出力を変数に格納して再利用 SG_ID=$(aws ec2 describe-security-groups \ --filters "Name=group-name,Values=my-sg"

    \ --query 'SecurityGroups[0].GroupId' --output text) aws ec2 authorize-security-group-ingress --group-id "${SG_ID}" ... IDのコピペミスで別のリソースを変更してしまう事故を防げる 13
  8. 変数展開 — 文字列操作 外部コマンドなしでパス操作ができる path="/var/log/nginx/access.log" ${path%/*} # → /var/log/nginx (dirname

    相当) ${path##*/} # → access.log (basename 相当) ${path##*.} # → log ( 拡張子取得) 覚え方: # は先頭を削除、 % は末尾を削除。1個で最短、2個で最長 # 拡張子の一括変換 for f in *.jpeg; do mv "${f}" "${f%.jpeg}.jpg"; done 14
  9. 変数展開 — デフォルト値 シェルスクリプトや関数で引数を安全に扱う手法 # デフォルト値の設定($1 はスクリプトの第1 引数) # 引数が未指定なら

    8080 を使う PORT=${1:-8080} # 必須チェック(未設定ならエラーメッセージを出してスクリプトを終了) ${DATABASE_URL:?DATABASE_URL を設定してください} 15
  10. コマンド展開 — コマンド結果をその場で使う Before: digの結果をコピペしてgrepに貼り付け dig +short api.example.com # →

    x.x.x.x をコピペ grep "x.x.x.x" /var/log/nginx/access.log After: $(command) で直接展開 grep "$(dig +short api.example.com)" /var/log/nginx/access.log コピペした値が古い問題を回避できる ※ スクリプト内での安全な使い方は後述 17
  11. コマンド展開の活用例 # Git ハッシュをdocker イメージのタグに docker build -t "myapp:$(git rev-parse

    --short HEAD)" . # 日付付きバックアップ(ブレース展開との合わせ技) cp important_file{,_$(date +%Y%m%d).bak} 18
  12. プロセス置換 <() — コマンド出力をファイルとして扱う ※ Bash/Zsh で利用可能(POSIX sh では不可) 一時ファイル不要の比較の例

    # Before: 一時ファイルに書き出してdiff kubectl get pods -n staging | sort > /tmp/staging.txt kubectl get pods -n production | sort > /tmp/prod.txt diff /tmp/staging.txt /tmp/prod.txt # After: 1 行で完了 diff <(kubectl get pods -n staging | sort) <(kubectl get pods -n production | sort) 19
  13. コマンド展開の注意点 インラインの $(command) は内側のコマンドが失敗しても外側のコマンドがそのまま実行さ れる set -e を使っていても、インライン展開の失敗は検知されない set -e

    # dig が失敗 → 空文字列で grep が実行される(スクリプトは停止しない) grep "$(dig +short api.example.com)" /var/log/nginx/access.log シェルスクリプト内では変数に格納してから利用する方が安全 set -e # dig が失敗 → スクリプトが停止する IP=$(dig +short api.example.com) grep "${IP}" /var/log/nginx/access.log 20
  14. まとめ 展開 用途 覚える構文 ブレース展開 パスをまとめる・連番 {a,b} , {1..10} 変数展開

    再利用・文字列操作 ${var} , ${var%pat} コマンド展開 結果を文字列として使う $(command) プロセス置換 結果をファイルとして扱う <(command) コピペ = 人間の目と手が介在するたびにミスの余地が生まれる 展開を使えば構造的に防げる 22
  15. 明日から使える小技 # !! — 直前コマンドをsudo 付きで再実行 sudo !! # !$

    — 直前コマンドの最後の引数を再利用 cat /etc/nginx/sites-available/default vim !$ # Esc . — !$ のインタラクティブ版(連打で遡る) zshユーザー向け補足 {$x..5} が動く(Zshでは変数展開がブレース展開より先に処理されるため。Bashでは 動かない) =(command) でシーク可能なプロセス置換が使える 27
  16. 付録: 変数展開 — デフォルト値・長さ 構文 説明 例 ${VAR:-val} 未設定/空ならvalを返す ${PORT:-8080}

    ${VAR:=val} 未設定/空ならvalを代入して返す ${CONFIG_DIR:=/etc/myapp} ${VAR:+alt} 設定済みかつ非空ならaltを返す ${VERBOSE:+--verbose} ${VAR:?msg} 未設定/空ならエラー終了 ${DB_URL:? 未設定} ${#VAR} 文字列の長さ ${#PATH} ${VAR:offset:length} 部分文字列 ${STR:0:5} 28
  17. 付録: 変数展開 — パターン削除・置換・変換 構文 説明 例 ${VAR#pattern} 先頭から最短一致を削除 ${path#*/}

    ${VAR##pattern} 先頭から最長一致を削除 ${path##*/} → basename ${VAR%pattern} 末尾から最短一致を削除 ${path%.*} → 拡張子除去 ${VAR%%pattern} 末尾から最長一致を削除 ${path%%.*} ${VAR/old/new} 最初の一致を置換 ${STR/hello/Hi} ${VAR//old/new} 全一致を置換 ${STR//hello/Hi} ${VAR^^} 全て大文字(Bash 4.0+) ${var^^} → HELLO ${VAR,,} 全て小文字(Bash 4.0+) ${var,,} → hello 29
  18. 付録: ブレース展開一覧 構文 説明 展開結果 {a,b,c} カンマ区切り a b c

    {1..10} 連番 1 2 3 ... 10 {01..10} ゼロパディング 01 02 03 ... 10 {1..10..2} ステップ指定(Bash 4.0+) 1 3 5 7 9 {a..z} 英字の連番 a b c ... z pre{a,b}post 前後に文字列付加 preapost prebpost {a,b}{1,2} 組み合わせ a1 a2 b1 b2 file{,.bak} 空文字列との組み合わせ file file.bak ※ Bashではブレース展開が最初に処理され、その後にコマンド展開が評価される。そのため cp file{,_$(date +%Y%m%d).bak} のような組み合わせが成立する 30
  19. 付録: zsh特有の展開フラグ フラグ 機能 例 ${(U)var} 全文字を大文字に ${(U)var} → HELLO

    ${(L)var} 全文字を小文字に ${(L)var} → hello ${(C)var} 各単語の先頭を大文字に ${(C)var} → Hello World ${(j:sep:)array} 配列要素をsepで結合 ${(j:,:)array} ${(s:sep:)var} 文字列をsepで分割して配列化 ${(s:,:)var} ${(f)var} 改行で分割 ${(f)var} ${(o)array} 昇順ソート ${(o)array} ${(O)array} 降順ソート ${(O)array} 33
  20. 付録: zsh特有の機能 機能 説明 Bashでの代替 ${=var} 明示的に単語分割 クォートなしの ${var} ${var:h}

    dirname相当 ${var%/*} ${var:t} basename相当 ${var##*/} ${var:e} 拡張子取得 ${var##*.} ${var:r} 拡張子除去 ${var%.*} =(command) 一時ファイルベースのプロセス置換 なし(手動で一時ファイル作成) {$x..5} ブレース展開内で変数が使える eval echo {$x..5} 34