みんな大好きなbashコマンドを極めてみる

目次
- ▼概要
- ▼一般コマンド系
- ▼スクリプト系テクニック
概要
ちょこっとした処理をするには非常ぉ~~~に便利なbashコマンドやbashスクリプト。
しかし、ちょっとクセがあったりして、そこまで頻繁に使うわけでないので、覚えるのはちょっと難あり。
まあここでは、極めるってほどの話しではないですが、LinuxやUnix/BSD系で、自分もよく、ちょくちょく、たま〜に使う、便利そうなbashコマンドとその機能・オプション等を、私の独断と偏見で厳選して、備忘録的に記録しておきます。
※基本、Linux系メインで記載しておりますので、一部、Unix、BSD系、MAC等や、バージョンによってもオプション等が異なる場合がありますので、ご了承ください。
一般コマンド系
ファイル内検索(grep)
主にgrepのお話し。よく使うものだけ抜粋。
圧縮ファイルは、zgrep , bzgrepコマンドを使う。
変数に特定の文字が含まれているかチェックする場合も活用。[ “$(echo $tmp|grep ‘aaa’)” ] など。
基本形式
grep [オプション] 検索文字列 ファイル名
grep コマンド(オプション)
オプション | 機能など |
---|---|
-i | 大文字小文字を区別しない |
-w | 単語で検索 |
-E |
拡張正規表現
正規表現にエスケープ文字「¥」が不要になったりするので便利 |
-v | これに一致したものを除外 |
-B数字 | 検索箇所のx行前も表示(Before) |
-A数字 | 検索箇所のx行後も表示(After) |
-r | 指定したフォルダ以降を再帰的に全ファイルgrepしてくれる |
-l |
ファイル名のみ表示
(複数ファイル存在時のみ有効) |
-h |
ファイル名を表示しない
(複数ファイル存在時のみ有効) |
grep コマンド(正規表現)
正規表現 | 機能など |
---|---|
. | 任意の1文字 |
* | 直前の文字を0回以上繰り返し |
¥+ | 直前の文字を1回以上繰り返し |
¥{n,m¥}
¥{n¥} ¥{n,¥} |
直前の文字をm回以上n回以下の繰り返し
直前の文字をちょうどn回の繰り返し 直前の文字をn回以上の繰り返し |
^ | 行頭 |
$ | 行末 |
[a-z]
[A-Z] [0-9] |
範囲内の任意の1文字 |
[^指定文字] | 指定文字を除外して検索 |
¥(検索1¥|検索2¥) |
「検索1」か「検索2」をor検索
さらに複数あれば、「\|」パイプで繋げる |
¥正規表現文字列 |
エスケープ文字。上記の正規表現を通常文字として扱う、
¥. →「.」ドット文字として扱う、など |
ファイル名検索
ファイル名の検索だけです。 昔はlocateコマンドが非常に便利だったんですが、今は標準では亡き…。
ファイル名検索
パス配下のファイル名を検索。
ワイルドカードを使う場合は、シングルコーテ ーション(’)で括る必要あり。
find パス -name 'xxx*xxx.log'
雑なやり方。
ls -R で、フォルダ配下を再帰的に表示してくれる。
権限とかファイル日時とかも探したいときに役立つ。
ls -FlasR パス | grep "xxx*xxx.log"
Webアクセス系(curl)
Webアクセスするためのコマンド。 wgetはまぁいいや(笑)
基本形式
curl [オプション] URL [オプション]
curlコマンド(オプション)
オプション | 機能など |
---|---|
-i |
ヘッダ情報を最初に表示
ボディ部も表示する |
-I |
ヘッダ情報のみを表示
ボディ部は表示しない |
-s |
サイレント表示
ダウンロード状況などの進捗を表示しない |
-sS | 進捗はいらないけどエラーは表示される |
-k |
SSL/TLS証明書の正当性チェックをパスする
自己証明書などはこれを使用 |
-XPOST https://URL/ -d “POSTデータ” |
POSTデータの送信
データは「aaa=1&bbb=2&・・・」の表記 |
curl -c cookie.txt | setクッキーの保存 |
curl -b cookie.txt |
保存されているクッキーを送信
set cookieがあれば、ここに保存もしてくれる |
-o filename.log | 結果をファイルに保存 |
-O | 結果をURL末尾の名前でファイルに保存 |
-L |
リダイレクト対応。指定したlocationに自動でアクセスしてくれる
デフォルトはリダイレクト非対応で、302とか返ってきても無視して結果のみ出力 |
-H “User-Agent: Googlebot/2.1” |
ヘッダ情報を設定
(ここの例ではユーザーエージェント) |
-F “file=aaa.log” | ファイルのアップロード |
-u user:password | BASIC認証 |
置換系
変数やパイプ後の置換など。
sed コマンド
検索文字列を置換文字列に置換。
正規表現を使えば複雑な置換も可能。
‘s|文字列1|文字列2|g’ とか区切り文字は変更可能。
echo "xxxx" | sed -e 's/検索文字列/置換文字列/g'
-iオプションを付けると、ファイル直接置換する。
-iオプションの後ろは、バックアップファイルを作成するときの末尾に付ける文字列を指定するが、バックアップ不要のときは、下記のように指定する。
(Linux) sed -i -e 's/検索文字列/置換文字列/g' filename (FreeBSD) sed -i '' -e 's/検索文字列/置換文字列/g' filename
bash変数内の文字列置換
コマンド(結果例) | 機能など |
---|---|
${変数/検索文字列/置換文字列} | 最初にマッチした部分のみ置換 |
${変数//検索文字列/置換文字列} | マッチする部分、全て置換 |
${変数#先頭からの削除文字列}
TMP=/var/www/html/tst/www/root echo ${TMP#/*/*/*/} tst/www/root |
先頭からの最短マッチ部分を削除
ここら辺以降はあんまり使わないかな。。 |
${変数##先頭からの削除文字列}
echo ${TMP##*/} root |
先頭からの最長マッチ部分を削除 |
${変数%パターン}
echo ${TMP%/*} /var/www/html/tst/www |
末尾からの最短マッチ部分を削除 |
${変数%%パターン}
echo ${TMP%%html/*} /var/www/ |
末尾からの最長マッチ部分を削除 |
(おまけ)bash変数のオフセット位置からの取得
最初の数値がオフセット位置、その後が文字列長さを指定。
$ tmp="abcdef" $ echo ${tmp:0:2} ab
文字列長さを省略すると、最後まで出力。
$ echo ${tmp:2} cdef
文字列長さがマイナスは、最大文字列長さから引いた長さを返してくれる。
$ echo ${tmp:0:-2} abcd
改行削除
改行削除されて、全てくっつく。
$ TMP="aaaa bbbb cccc " $ echo "$TMP" | tr -d '¥n' aaaabbbbcccc
sed版。sedはそのままだと改行コードを置換できないので、下記のようにする必要がある。 めんどいのであんまり使わないほうが良いかな…。
(Linux) $ echo "$TMP" | sed ':loop; N; $!b loop; s/¥n//g' (FreeBSD) $ echo "$TMP" | sed -e ':loop' -e 'N; $!b loop' -e 's/¥n//g' $ aaaabbbbcccc
ダブルクォーテーションで括らないと、改行の区切りがスペースになる。
echo $TMP aaaa bbbb cccc
空行削除
sedとか使うと複雑になるので、これが一番シンプルイズベスト。
$ echo "$TMP" | grep -v "^$" aaaa bbbb cccc
計算
簡易な足し算、引き算、割り算、掛け算など。
expr コマンド(整数のみ)
整数のみ計算。小数点は切り捨て。
演算の優先順位(掛ける・割る優先)も考慮される。
「%」は割り算の余り。
$ tmp=3 $ expr 7 - 12 \* 4 / $tmp -9
bc コマンド(小数点以下OK)
小数点以下の計算。 scaleで小数点以下、何桁まで表示するか設定。
$ echo "scale=4; 10.3/3.3-100" | bc -96.8788
演算精度を保つために計算結果は小数点以下6桁を保持し、表示は小数点以下2桁の場合。
$ tmp=$(echo "scale=6; 10.3/3.3-100" | bc) $ echo $tmp -96.878788 $ printf "%.2f" $tmp -96.88
bash組み込みインクリメント・デクリメント (加算・減算)
$(()) 内はインクリメント演算子が使え、$を書いても書かなくてもOK。
先頭に記述の場合、評価前にインクリメントした値を返す。
$ ii=3; echo "$((++ii)) $ii" 4 4 $ ii=3; echo $((--ii)) 2 2
末尾に記述の場合、評価後にインクリメントした値を返す。
$ ii=3; echo "$((ii++)) $ii" 3 4 $ ii=3; echo "$((ii--)) $ii" 3 2
先頭に記述の場合と同等。
$ ii=3; echo "$((ii+=1)) $ii" 4 4 $ ii=3; echo "$((ii-=1)) $ii" 2 2
ii=$((++ii))のような書き方をしなくても単体で使用可能。
また $? の返り値は、評価結果が0の場合は0、それ以外は1が返る特性がある。
$ ii=3; let ++ii; echo $ii 4
日時計算
日時の表示や計算など
dateコマンド
現在の日時(秒以下まで)を表示。
$(date ~) などで変数やファイル名などに入れたり、[ $(date +%Y%m%d) -lt 20210407 ] などで日時の比較にも便利。
$ date +%Y%m%d_%H%M%S.%N 20210326_094453.491610548
曜日
$ date +%a 金
UTC (1970-01-01 00:00:00) からの秒数(Unix時間)
$ date +%s 1616719469
Unix時間から戻す。
(Linux) $ date --date "@1616719469" (BSD系) $ date -r 1305730800 2021年 3月 26日 金曜日 09:44:29 JST
2021/03/03から、1年前と1ヵ月後。
(Linux)単位は他にday,hour,minute,secが使用可能。
(BSD系)単位は他にw(週),d,H,M,Sが使用可能。
(Linux) $ date --date '20210303 1 year ago 1 month ' +%Y-%m-%d (BSD系) $ date -v-1y -v+1m -j 202103030000 +%Y-%m-%d 2020-04-03
日時比較
本日が 2022/01/01 より過去なら、~を実行。
※-lt などの判定分は後述参照。
[ $(date +%Y%m%d) -lt 20220101 ] && ~
スクリプト系テクニック
主にスクリプトファイルを書くときに便利なものなど。
定番系
PATH設定
とりあえずこんな感じで、スクリプトの先頭に設定しておけば、めったにフルパスでコマンド記述しなくても良いかな~って感じ。
export PATH=$PATH:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
言語
基本、日本語が好きな人向け。
環境によって適宜。
export LANG=ja_JP.UTF-8
小技・便利系
スクリプトのカレントディレクトリ設定
現在実行しているスクリプトのディレクトリ名をここに設定。
これを最初に設定しておけば、他の関連ファイル・ログ等を作成する場合に、このディレクトリを起点に色々相対パスで指定できるので便利。
SCRIPT_DIR=$(cd $(dirname $0);pwd) LOG=$SCRIPT_DIR/tst.log
スクリプトのファイル名
現在実行しているスクリプトのファイル名をここに設定。
usageなどを作成する場合に便利。
SCRIPT_NAME=$(basename $0)
フォルダ作成
とりあえず「-p」オプションでフォルダ作成しておけば、フォルダがあってもエラーが出ないので、いちいちフォルダ存在チェックがいらない。(おうちゃくですみません。。。)
mkdir -p /xxx/xxx/xxx/
ファイルのクリア
いちいち「ファイル存在チェック→削除→クリエイト」としなくても、一発で済む。ファイルがなければ作成もするし。
オプション「-n」があると、完全クリア。
オプション「-n」がないと、最初に改行コードが入るが、通常は気にしないレベルかと。
echo -n > bbb.log echo > bbb.log
ファイルのインクルード
先頭に「.」を付けることで、共通的に使用するようなファイルを、その場所に持って来る形でincludeできる。
. ./define.conf
ファイルの中身を1行ずつ読み込む
注意すべきとして、このケースでは、while内の変数はループ終了後に変数の値を引き継がない。
$ { tmp=ABC cat ファイル名 | while read LINE;do tmp="$LINE" done echo $tmp ; } ABC
下記の場合は、whileループ終了後でも変数がそのまま使える。
基本、こちらが推奨。
$ { tmp=ABC while read LINE; do tmp="$LINE" done < ファイル名 echo $tmp ; } (結果はファイルの末尾の行を表示)
CSVファイル(コンマ(,)区切り)の場合の例
while IFS=, read column1 column2 ; do echo "$column1 $column2" done < CSVファイル名
この場合、改行だけでなく、スペースも区切り文字として分割されてしまうので注意。
for LINE in $(cat ファイル名) ;do echo "$LINE" done
変数系
特殊変数
特殊変数 | 機能など |
---|---|
$0 | 実行した際のファイル名(パス含む) |
$1~n | 実行時の引数。1番目、2番目、、、n番目 |
$# | 引数の数 |
$@ | 引数すべて |
$? |
直前のコマンドの実行結果の返り値 通常、正常時:0以上、異常時:-1以下 値はコマンドによりけり |
引数のオプション解析
下記はgetopts による解析例。
デメリットとして、引数のあとにオプションを使用できない、ロングオプション不可がある。
getopts直後の「:」コロンについて。
先頭の「:」は、エラーを自前で処理。なければ自動でエラー表示。
文字列のあとの「d:」は、オプションの後の引数を$OPTARGで取得可能。
※もっと多機能を求めるならGNU版getoptをお勧めしますが、BSD系との互換性を考えると、とりあえずgetopts レベルで良いかな。そこまでガッツリ作るつもりないし(笑)
while getopts ":ad:h" OPT do case $OPT in a) AllFlg=1;; d) optDir=$OPTARG ;; h) usage;exit ;; :) echo "Error: オプションに引数がないよ。"; usage; exit -2;; ¥?) echo "Error: そんなオプションはないよ。"; usage; exit -1;; esac done # getopts分の引数値移動 shift $(($OPTIND - 1))
自前で解析する場合。この例では、変数opt_1,opt_2,・・・に引数1、引数2、・・・が入る。
ii=0 for OPT in "$@" do case "$OPT" in -a | --all) AllFlg=1;; -d) [ "${2:0:1}" = "-" ] && { echo "Error: -d 引数ないよ。";exit -1;} ; optDir="$2";shift ;; -*) echo "Error: そんなオプションはないよ。"; usage; exit -1;; *) eval "opt_$ii='$OPT'";let ++ii ;; esac shift done
if判定
形式
形式 | 機能など |
---|---|
if [ 条件 ] ; then # 正の処理 [else # 偽の処理 ] fi |
通常のif文 |
[ 条件 ] && 正の処理 [ || 偽の処理 ] | 簡略系 |
[ 条件 ] && { 正の処理 正の処理 ・・・ ; } [ || 偽の処理 ] |
複数行の例 |
条件 - ファイル・ディレクトリの判定
条件 | 機能など |
---|---|
[ -f ファイル名] | ファイルが存在しているなら真 |
[ -s ファイル名] | サイズが 0 より大きければ真 |
[ -d フォルダ名 ] | ディレクトリが存在しているなら真 |
[ -e ファイルorフォルダ名] | ファイルかディレクトリが存在しているなら真 |
[ -r ファイルorフォルダ名] | 読み取り権限があれば真 |
[ -w ファイルorフォルダ名] | 書き込み権限があれば真 |
[ -x ファイルorフォルダ名] | 実行権限があれば真 |
条件 - 数値の比較
コマンド | 機能など |
---|---|
[ $tmp -eq 1 ] | = イコール |
[ $tmp -ne 1 ] | != 否定 |
[ $tmp -lt 1 ] | < 左側が小さい場合、真 |
[ $tmp -le 1 ] | <= |
[ $tmp -gt 1 ] | > 左側が大きい場合、真 |
[ $tmp -ge 1 ] | >= |
条件 - 文字列の比較
コマンド(結果例) | 機能など |
---|---|
[ "$tmp" = "test" ] | イコール |
[ "$tmp" != "test" ] | 否定 |
[ -z $tmp ] [ "$tmp" = "" ] |
文字列長が 0 の場合、真 |
[ -n $tmp ] | 文字列長が 0 より大きい場合、真 |
その他bash制御系
whileはまあいいや。
for文
ループを抜ける場合は break;
ループの先頭に戻って継続する場合は continue;
コマンド(結果例) | 機能など |
---|---|
for ((ii=0; ii < 10; i++)); do echo $ii done |
定番の指定回数分ループ |
for 変数 in 値のリスト; do | 値のリストは、スペース区切り |
最後に
なんか色々書いていたら、思っていたよりボリューミーになってしまって。もっと簡単に書きたかったのですが…。
まだまだbashには奥深い技やコマンドが多々ありますので、また機会があれば第2弾があるかもしれません。
▼第2弾