Skip to content

Linuxシェルスクリプトmemo

inoue.h edited this page Aug 17, 2023 · 3 revisions

Home > Software > ソフトウエア開発・PC管理のメモ帳 > this page (このページ)


Linuxでテキスト処理したり、ファイルのテキスト検索をするコマンドを個人的にメモしたものです



Table of Contents

コマンドライン編集のキーアサイン

カーソル移動

 右へ : →/Ctrl+f(1文字) Esc+f(1ワード) Ctrl+a(行頭)
 左へ : ←/Ctrl+b(1文字) Esc+b(1ワード) Ctrl+e(行末)

削除

 その位置1文字 : Del/Ctrl+d
 左へ1文字 : Bs/Ctrl+h
 行頭まで全て : Ctrl+u
 行末まで全て : Ctrl+k

コマンドライン検索(インクリメンタル)

 検索開始(現在位置から過去へ) : Ctrl+r
 同一条件で再検索 : Ctrl+r
 最古のコマンドへ : Esc+<
 最新のコマンドへ : Esc+>

直前のコマンド再実行

 !!

補完

 コマンド名・ファイル名補完 : Tab
 コマンド名強制補完 : Esc+!
 ファイル名強制補完 : Esc+/
 ユーザ名補完 : Esc+~
 変数名補完 : Tab(変数を$で書きはじめたとき) Esc+$(変数を$で書きはじめないとき)

過去に実行したコマンドを表示する

 history

ジョブ制御:フォアグラウンド、バッググラウンド

ジョブ一覧の表示

 jobs

ジョブを一時停止

 Ctrl + Z

一時停止中のジョブを、フォアグラウンドで再開

 fg [ジョブ番号]

一時停止中のジョブを、バックグラウンドで再開(コマンド実行時に & を付けるのと等価)

 bg [ジョブ番号]

サブシェルで実行されるかどうか

現在のシェル内で実行される例

 source ./test.sh

サブシェルが起動され、その中で実行される例

 sh ./test.sh
 ./test.sh

条件実行

終了ステータスによる判断

command1の終了ステータス0(真)のときに実行

 command1 && command2

command1の終了ステータス0以外(偽)のときに実行

 command1 || command2

ファイル名のマッチング

検索して条件を満たしたファイル名すべてに展開される

 0文字以上の任意の文字 : *
 任意の1文字 : ?
 パターン内の任意の1文字 : [pattern] (例 [0-9], [0-9a-z])

指定した文字列に展開される

 {str1,str2,..} : 例 img{001,002,003}.jpg

空白(スペース)文字を含んだファイルの処理

forで切り分けるときの区切り文字を、「空白文字or改行」から「改行のみ」に変更する例

IFS_BACKUP=$IFS
IFS=$'\n'
for fullpath in $*
do
   echo $fullpath
   file $fullpath
done
IFS=$IFS_BACKUP

上の例は、スクリプトファイルの引数としてファイル名を受け取る場合、直接スクリプト内に記述する場合は次のようにすればよい。

for fullpath in `find . -type f -print`

特殊文字の無効化

ファイル名に * や ? を使ったものなどを扱うとき

 / : 直後の1文字の特殊性を無効化
 '...' : 囲まれた範囲内の特殊性を無効化
 "..." : 囲まれた範囲内の特殊性を無効化(ただし、変数の$は有効)

リダイレクト

 > または 1> : 標準出力 (例:command > output.txt)
 2> : 標準エラー出力

組み合わせて用いる例として

 command 1> output.txt 2> error.txt : それぞれ別のファイルに保存する
 command 1> output.txt 2>&1 : エラー出力も同一ファイルに保存する

標準入力(キーボード)で入力した内容を、ファイルに保存する例

 cat > output.txt

出力を切り捨てる例

 command > /dev/null 2>&1 : すべての出力を切り捨てる
 command > output.txt 2> /dev/null : エラー出力のみ切り捨てる

変数

シェル変数の定義、削除

 val=str : 変数valに値を代入
 export val : 変数valをサブシェルでも利用できるようにエクスポート
 export val=str
 unset val : 変数valの定義を削除する
 $val : 変数を参照 (例:echo $val)
 ${val} : 変数を参照

変数一覧の表示

 set

シェルの引数

 $1, $2, ... : シェル起動時に渡された引数
 $* : 全ての引数を結合した文字列。
       $* = $1 + " " + $2 + " " + $3 + ...
 "$*" : 全ての引数を結合した文字列。結合時に$IFSの文字を挟む(未定義時は空白文字)
       $* = $1 + "$IFS" + $2 + "$IFS" + $3 + ...
 "$@" : 全ての引数を結合した文字列
 $# : 引数の総数(数値)。1, ...
 $0 : シェルスクリプト名

引数のシフト

 shift n : n個ずらす。結果として、$#で返される総数も減る

 shift 1 : $1を切り捨て、$2を$1に、$3を$2に、...

関数の引数

function func()
{
   echo $1
   echo $2
}

func one two

シェル引数でなく、関数呼び出し時の引数が参照される

シェルの引数を解析

for $str in "$@"; do
   echo $str
done

上記の実行結果

 $ sh test.sh "param one" two
  param one
  two

$@"$@"のように囲った場合は、引数で"..."で囲まれた部分は一つの文字列と認識できる

シェルプロセスの実行環境を取得

 $? : 直前のコマンドの終了ステータス(0:成功、1~125:失敗、126:実行不可、127:コマンド不存在)
 $$ : シェルのPID

変数の値に応じた自動補完等

 ${val:-str} : valが定義されていなければstrを返す、定義されていればその値を返す
 ${val:=str} : valが定義されていなければstrを定義して返す、定義されていればその値を返す
 ${val:n} : valの先頭からn文字スキップして、それ以降を返す
             val="one two"
             echo ${val:2}  → "e two"を表示
 ${val:n,m} : valの先頭からn文字スキップして、それ以降m文字を返す
 ${@:n,m} : シェル引数を扱う。文字ではなく、引数毎の数えかたとなる
             echo ${@:2,3} → "two three four"

特別に定義されているシェル変数

 PATH : コマンド検索パス
 PS1 : プライマリシェルのプロンプト(例:PS1=[\u@\h \W]\$)
 HOME : ホームディレクトリ
 LANG : 言語環境(例:LANG=ja_JP.UTF-8)

変数をセットするスクリプトを作成する場合、「サブシェルで実行されるかどうか」セクションで説明しているように、実行元のシェルに結果を反映させるためには source コマンドで実行する必要がある。

配列

値のセット

 val=( str1 str2 str3 )
 val=( [1]=str1 [3]=str3 )
 val[5]=five

値の参照

 ${val[n]} : インデックスnの値を参照(例:${val[3]})
 ${val[*]} : 全て結合(間はスペース文字)して1つの文字列とする
 "${val[*]}" : 全て結合(間は$IFSにセットされた文字)して1つの文字列とする
 ${#val[*]} : 配列の要素数
 ${#val[n]} : 配列の要素n番の文字列の長さ

コマンド、数式や条件評価

コマンドの実行結果を変数に取り込む

 val = $(cmd param1 param2)

例:/dev/sda12の利用可能サイズを変数に格納

 val = $(df | grep sda12 | awk '{print $4}')

算術式評価結果を変数に取り込む

 val = $((算術式))

val1 = 10
val2 = 5
sum = $((val1 + val2))

フロー制御(if, for, case, while)

if構文

if 条件式
then
   処理を記述
elif 条件式
then
   処理を記述
else
   処理を記述
fi

スクリプトの引数を判定するif文の例

if [ $1 == "-help" -o $1 == "-?" ]
then
   echo "ヘルプ文の表示"
   exit
fi

if [ $# -ne 1 ]
then
   echo "引数は1個です"
   exit
fi

あるプロセス(progA)が存在したら、特定のプログラム(progB)を実行する例 (1行で記述)

[ -n "$(pgrep -f /usr/bin/progA)" ] && /usr/bin/progB

for構文

 for val in val1 val2 val3 ...
 do
   処理を記述
 done
 for ((i=0; i>8; i++))
 do
   処理を記述
 done

連番の付いた空ファイルを作成する例

for ((i=0;i<10;i++)); do echo -n > temp$i.tmp; done

行を分けて書く場合は

for((i=0;i<10;i++))
do
  echo -n > temp$i.tmp
done

select構文

 select val in val1 val2 val3 ...
 do
   処理を記述
 done

Cのselect caseと違い、valにそれぞれの値をセットして順次実行する

case構文
 case val in
   val1)
     処理を記述
     ;;
   val2)
     処理を記述
     ;;
   *)
     処理を記述
     ;;
 esac

while構文

while 条件式
   処理を記述
done

while test $i -gt 0
   echo $i
   ((i--))
done

until構文

until 条件式
   処理を記述
done

条件式が偽の場合にループする

ループの中断

for, while, until, select を中断する

 break

n個のループを抜け出すには

 break n

ループのスキップ

 continue

testコマンド

条件式を評価し、ステータスコードを返す

 test 条件式
 test ! 条件式 : 条件式が偽のときに真を返す
 test 条件式1 -a 条件式2 : ふたつの条件式が共に真の場合のみ真を返す (AND)
 test 条件式1 -o 条件式2 : ふたつの条件式のどちらかが真の場合のみ真を返す (OR)

ファイルの検査

 test -a ファイル名 : ファイルが存在する場合に真を返す
 test -b ファイル名 : ブロックデバイスの場合に真を返す
 test -c ファイル名 : キャラクタデバイスの場合に真を返す
 test -d ファイル名 : ディレクトリの場合に真を返す
 test -f ファイル名 : 普通のファイルの場合に真を返す
 test -h ファイル名 : シンボリックリンクの場合に真を返す
 test -r ファイル名 : 読み込み許可ありの場合に真を返す
 test -w ファイル名 : 書き込み許可ありの場合に真を返す
 test -s ファイル名 : ファイルサイズがゼロ以上の場合に真を返す
 test -x ファイル名 : ファイルが存在し実行可能であれば真を返す
 test ファイル1 -nt ファイル2 : ファイル1が、2より更新時刻が新しい場合真
 test ファイル1 -ot ファイル2 : ファイル1が、2より更新時刻が古い場合真

文字列の検査

 test -z str : 文字列の長さがゼロの場合に真を返す
 test -n str : 文字列の長さがゼロ以上の場合に真を返す
 test str1 = str2 : 「==」ではなく「=」であることに注意
 test str1 != str2
 test str1 < str2 : 数値比較ではなく、文字列のソーティングで比較する
 test str1 > str2

数値の検査

 test val1 -eq val2
 test val1 -ne val2
 test val1 -lt val2 : val1 < val2
 test val1 -gt val2 : val1 > val2
 test val1 -le val2 : val1 <= val2
 test val1 -ge val2 : val1 >= val2

そのほかの条件式評価方法
[ ファイル演算条件式 ]という方法も使える

 [ -f ファイル名 ] : test -f ファイル名 と等価

(( 数値演算条件式 ))という方法も使える

 ((val1 -eq val2)) : test val1 -eq val2 と等価

if構文中でtest構文を利用する例

if test val1 -eq val2
then
   処理
fi

これと等価なのは(構文上、処理は1行だけしか出来ない)

 ((val1 -eq val2))
 処理

また、ファイル演算の場合は

 [[-f ファイル名]]
 処理

ファイル検索して見つかったファイル(ディレクトリは除外)を処理する例

for i in *; do [ ! -d "$i$ ] && echo "$i"; done
for i in *; do if test ! -d "$i" ;  then echo "$i"; fi; done

あるファイルが存在する場合、それを削除する例

[ -f /var/log/logfile.txt ] && rm /var/log/logfile.txt

スクリプト制御(exit, return)

スクリプトを終了する

 exit

また、終了コードを指定する場合は(例:真は0、偽は1~の値をセットする)

 exit n

関数を終了する(終了コードが必要な場合は、nを指定する)

 return n

ユーザ入力、画面出力(read, printf)

標準入力から読み込む

 read val1 val2 ...
 read -p "prompt" val

成形して出力する(Cのprintf関数と同じ)

printf "%10s %X\n" str1 val1