Shell Script 入門

Shell Script 入門

Basic

制御構文

  • if

i=10
if [ $i -le 5 ]; then
    i=`expr $i + 5`
elif [ $i -le 10 ]; then
    i=`expr $i + 10`
else
    i=`expr $i + 1`
fi
  • for

max=10
for ((i=0; i < $max; i++)); do
    echo $i
done
  • while

read varのようにすると入力を受付け、変数varに格納される。

  • case

/etc/rc0.d/S01halt

条件判定部分は正規表現が使える。

  • until

特殊変数

  • $#

    • コマンドラインの引数

  • $1$9, $0

    • 引数それぞれ。 Positional Parameters という。

  • $*

    • $0 以外のコマンドライン引数

  • $@

    • $* と類似。ただし $@ とした時、位置パラメータを評価せずにコマンドに渡すことが出来る

  • $?

    • シェルが最後に実行したコマンドの終了状態を保持している。ほとんどのコマンドは成功時には0を返す

  • $$

    • 現在のシェルのプロセス番号を保持している

  • $-

    • シェルにセットされているオプションを保持している

  • $!

    • バックグラウンドで実行された直前のプロセスのプロセス番号を保持しています

  • Reference

  • Title: Shell 特殊変数

    • URL: https://qiita.com/a_yasui/items/ec4f75b300410af8958d

文字列

文字列操作

  • 文字列の一部抜粋

    • 左から : cut -c -7

    • 右から : cut -c ``expr ${#var} + 1 - 7``-

    • 左右から : cut -c 9-13

  • 大文字・小文字変換

    • tr "a-z" "A-Z"

  • 正規表現でマッチした文字列の取り出し

    • AWK : matchstr=echo "STRING" | awk '{match($0, /PATTERN/); print substr($0, RSTART, RLENGTH)}'

    • SED : matchstr=echo "STRING" | sed 's/.*\(PATTERN\).*/\1/'

    • GREP: matchstr=echo "STRING" | grep -o 'PATTERN'

  • 特殊文字のトリミング

    • 左側のトリミング後、右側のトリミング

    • タブやスペースを取り除きたい場合は、trimming_char=printf " \t"

  • ファイル名・ディレクトリ名の取得

    • ファイル名取得

      • basename

      • filename="${filepath##*/}" # 左側からの最大マッチング

    • ディレクトリ名取得

      • dirname

      • dirpath="${filepath%/*}" # 右からの最小マッチング

文字列抽出

  • ${var:-word} : $varが未定義か空文字の場合は文字列wordが読み出される

  • ${var-word} : $varが未定義の場合は文字列wordが読み出される

  • ${var:=word} : $varが未定義か空文字の場合は文字列wordが読み出され、かつ$varにも代入

  • ${var=word} : $varが未定義の場合は文字列wordが読み出され、かつ$varにも代入

  • ${var:?word} : $varが未定義か空文字の場合は文字列wordが読み出され、かつエラーの扱い

  • ${var?word} : $varが未定義の場合は文字列wordが読み出され、かつエラーの扱い

  • ${var:+word} : $varが未定義でも空文字でもなければ、文字列wordが読み出される

  • ${var+word} : $varが未定義でなければ、文字列wordが読み出される

  • $#{var} : $varの文字数

  • ${var#PATTERN} : 左端からPATTERNについて最小マッチングで切り落とされて読み出される

  • ${var##PATTERN} : 左端からPATTERNについて最大マッチングで切り落とされて読み出される

  • ${var%PATTERN} : 右端からPATTERNについて最小マッチングで切り落とされて読み出される

  • ${var%%PATTERN} : 右端からPATTERNについて最大マッチングで切り落とされて読み出される

  • ${@:2} : 二つ目以降の引数を取得

  • Reference

  • Title: Shell 特殊変数

    • URL: https://qiita.com/a_yasui/items/ec4f75b300410af8958d

文字クラス

一部の環境では動作せず、使わないほうが無難

  • [[:alnum:]] : 英数字。[0-9A-Za-z]

  • [[:alpha:]] : 英字。[A-Za-z]

  • [[:digit:]] : 数字。[0-9]

  • [[:lower:]] : 英字の小文字

  • [[:upper:]] : 英字の大文字。[A-Z]

  • [[:blank:]] : スペースとタブ

  • [[:punct:]] : 記号 ! " # $ % & ' ( ) * + , - . / : ; < = > ? @ [ \ ] ^ _ `` { | } ~

  • [[:xdigit:]] : 16進数。[0-9A-Fa-f]

(参考) 正規表現

環境変数

IFS

  • IFS(Internal Filed Separator)

    • 設定された値が、文字の区切りとして認識される

    • ファイル等を読み込んだりする場合に利用

      • CSVファイルの場合に,を設定

メタ文字セット

BRE(基本正規表現)

  • 置換後文字列用

    • : n番目の\(\)で囲まれた範囲にマッチした文字列

    • & : マッチした文字列全体

    • \x : メタ文字&またはsed等で正規表現の始まりを住めすために用いた文字自身を指定したい場合

    • \\ : \を指定する場合

(参照) どのUNIXコマンドでも使える正規表現

ERE(拡張正規表現)

  • BREのときと比較して\をつけないなど、他多数

Others

ファイルの新規作成と追記

ヒアドキュメント

ヒアストリング

終了ステータス

0で正常終了。正常ではないときは0以外の数字が終了ステータス。 テストコマンドでは正なら0、偽なら1、変な引数が指定されたら2のようにそれ以外の値が返される。

パイプで処理すると途中の処理のステータスが配列として格納される。bashで配列を扱うことができる機能

あるファイルがなければシェルスクリプトを終了するという処理の場合、以下のようにして書くことができる。

引数

  • コマンド名 -- -引数のように--を指定することで、これ以降の-引数はオプションではなく、引数として解釈する

    • 実行例

AWKとsed

AWK

  • 関数

    • printf

    • sprintf

    • sub

    • gsub

    • gensub

    • length(t)

    • split(s,a,fs)

    • substr(s,p,n)

    • index(s,t)

    • match(s,r)

    • tolower(s)

    • toupper(s)

  • 変数

    • ARGC

    • ARGV

    • ENVIRON

    • FILENAME

    • FNR

    • FS

    • NR

    • OFS

    • ORS

    • RS

NFは各行の列数を表す予約語

標準入力より前処理、後処理

文字列を表示

フォーマットを指定して表示。標準出力はしないため、一旦変数に文字列を書き出して出力

3行目のみ表示

3行目から4行目まで表示

cの行からdの行まで表示

CSVファイルの第3フィールドの合計値を求める場合

-F,のように指定すると文字列で区切る

sed

3行目のみ置換

2行目から最終行まで置換

bの行からdの行まで置換

指定した範囲(3行目から4行目を表示)。sedとしては入力された行をそのまま出力するのが基本動作なので-nを指定することで指定範囲の行が2行ずつ表示されることを抑えている

-nを指定しない場合

  • xargsは標準入力から読み込んだ文字列をしていしたコマンドに引数として渡すコマンド

    • -I@のようにオプションで文字を指定すると、別途その文字を指定した位置に引数として渡す

    • -n 1のようにいくつの引数を渡すかを指定

    • -P 5のように何並列でプロセスを立ち上げるかを指定。0を指定するとできるだけプロセスを使うように指定

jq

jq Manual (development version)

  • -rでダブルクオテーションを削除

  • []{}で囲むと配列形式やオブジェクト形式で出力可能

  • | @csvのように渡すとCSV形式で出力可能

  • | {InstanceId, Tags:(.Tags|from_entries)} | select(.Tags.Name | contains("test"))'のようにすることでタグ指定で対象の項目を取得。Tags:の部分は出力結果の表示名。from_entriesで"Key": "auto-stop""Value": "yes"のような形式を"auto-stop": "yes"にまとめる

  • | lengthで長さ取得

  • | unique[]で配列に対して、重複排除。最後に[]をつけない場合、配列で結果表示

  • | fromjsonで文字列化されたJSONを復元

  • jq '.events[] | .timestamp/1000 | todate'のように秒単位にした上で| todateを使用すると時間の表示形式を整形

  • jq '.Functions[] | {FunctionName, VpcId:(.VpcConfig.VpcId//"NoVPC")}'のように//を指定すると左側がNULLのときは右側の要素に置き換える。

  • jq -r '.Reservations[] | .Instances[] | [.InstanceId, (.Tags | if (.==null) then null else ([.[] | "\(.Key)=\(.Value)"] | join(",")) end)] | @csv'のようにif () then ~ else ~ endを仕様できる。また、join()で指定文字列で文字列の配列を1つの文字列に結合

デバッグ

  • デバッグ

    • 未定義変数参照時にエラー

      • スクリプトの冒頭に#!/bin/sh -uのように-uオプションを付与

      • set -uを宣言

  • トレース

    • スクリプトの冒頭に#!/bin/sh -xのように-xオプションを付与

  • デバッグメッセージの分離

    • FIFOパイプ

      • mkfifo /tmp/pipeしたらecho "test" > /tmp/pipeのように書き出す

      • 別端末からwhile [ 1 ];do cat /tmp/pipe;done

  • パイプの中身

    • 途中でtee /dev/stderrにリダイレクトすることやFIFOパイプを利用

Others

grepでタブ記号が入っている場合の検索

タブ記号をスペースに置き換える。[:space:]は文字クラスを表し、タブや半角スペースなどの空白文字を指す

grepはデフォルトで基本正規表現。-Eオプションで拡張正規表現が利用でき、{5}で5回繰り返すといった表現が可能になる。

  • wcコマンド

    • -m : ロケールを考慮した文字数カウント

    • -l : 行数カウント

sed 's/./&\n/g'で文字ごとに改行できるので、行数を数えることでも計算可能。grep -o .で任意の一文字を検索して一行ごとに出力。

  • unique -c : カウント

<()はプロセス置換でbashの機能

HTMLの編集

コメントアウト削除

タグ削除。以下、実体参照が正しく使用されている場合

ファイルの同期

sedでまとめて置換

sedで置換するルールを予めファイルに列挙しておいてまとめて置換することができる

sedで部分一致箇所の抜粋

()で囲っておくと、\1のようにして取り出せる

Apacheのアクセスログの分析例

  • 改行やスペースを除く、文字でないバイナリを除去する

  • データ内の区切り文字以外の"や区切り文字を含んでいてっもフィールドを区切れるようにバックスラッシュは\\と記録されているので、これを%5Cにエンコーディング

  • "\"と記録されているので、これを%22にエンコーディング

IPアドレスのソート

以下の書籍等を参考にさせていただき、自分用の備忘録にまとめました。

Others

Last updated