dullwhaleのメモ帳

何度も同じことを調べなくてよいように...

個別の記事を作るほどでもないシェルのスニペット・アイデア

お決まり

シェルスクリプトの先頭に書くやつ

#!/bin/bash
set -euo pipefail
readonly SCRIPT_DIR=$(cd $(dirname $0) && pwd)

定番のフィルタコマンド

そのgrepは本当に必要?

sedを上手く使うとgrep | sedのような事前のgrepが不要になる場面も多い。 例えば次の入力をパイプで受け取り、50744だけを抽出したいとする。

p50744
f5

次のようにgrep+sedgrep+trで書くこともできるが

前のコマンド | grep '^p' | sed 's/^p//'
前のコマンド | grep '^p' | tr -d p

sedだけで書くこともできる。

# GNU版
前のコマンド | -n 's/p\([0-9]\+\)/\1/p'
# macOS/BSD版
sed -nE 's/p([0-9]+)/\1/p'

ただしsedの可読性が下がるようなら、素直にgrepを使え。

パイプで1行目だけ読み飛ばす

tail -n +2

ここで+2は2行目以降を出力することを意味する。 先頭2行を読み飛ばしたいなら、3行目以降を出力すれば良いから次のようにすれば良い。

tail -n +3

pasteコマンドを使ったhack

全ての行を特定のデミリタで結合するために使える。

paste -sd,

例えばinput.txtが次の内容の場合

a
b
c

次のようになる。

% paste -sd, input.txt
a,b,c

行のデータの頭と尻に文字を付加してプログラムの配列として使えるスニペットを作成

行をシングルクォーテーションで囲み、後ろにカンマを追加する。

sed -e "s/^/'/" -e "s/$/',/"

出力例

cat test | sed -e "s/^/'/" -e "s/$/',/"
'a',
'b',
'c',

testファイルの中身

a
b
c

sudo関連

パイプやリダイレクトを含めたコマンドをsudoで実行したい

/bin/shでまとめてしまえばよい。

sudo /bin/sh -c "command"

terraform関連

terraformのtargetオプションで指定するリソースをシェルで作る。

次のようなファイルtargets.txtがあるとする。

type.resource-name1
type.resource-name2
type.resource-name3

このファイルを読み取り、terraformのtargetオプションに渡す文字列を作りたい。

terraform plan -target={type.resource-name1,type.resource-name2,type.resource-name3}

これで作れる。サブシェル()で実行すればさらに楽。

% paste -sd, targets.txt | sed -e 's/^/{/' -e 's/$/}/'
{type.resource-name1,type.resource-name2,type.resource-name3}

雑多なもの

DNSメッセージを見やすくする。DNSメッセージは16bitごとにおおまかな区切りがあるから、このように分けると読みやすい。

xxd -b -c 2 dns.bin