#author("2019-04-03T16:30:25+00:00","","")
#author("2019-06-02T01:06:03+00:00","","")
#topicpath
* 目次 [#dc23a09c]
#contents();

////////////////////////////////////////////////////////////////////////////////
* コマンド履歴 [#c7be7af5]
//==============================================================================
** 履歴保存先ファイルの指定 [#dfd1089a]
- コマンド履歴は、通常は ${HOME}/.bash_profile に保存される。これを別なファイルに保存したい場合は、
 export HISTFILE=<新しいコマンド履歴ファイル名>
とする。&br;
例えば、[[screen>App/screen]]でセッション毎にコマンド履歴を保存したい場合に、セッション毎のコマンド履歴ファイルを指定するなど。
 if [ "${STY}" != "" ]; then
     export HISTFILE=${HISTFILE_DIR}/${TERM}.${STY##*.};
 fi

//==============================================================================
** 履歴にタイムスタンプを付加する [#d4fb0b12]
- 環境変数 HISTTIMEFORMAT にタイムスタンプフォーマットを指定する。この文字列は strftime(3) の書式文字列 として使われる。
 export HISTTIMEFORMAT="%F %T "

//==============================================================================
** 履歴を1コマンド毎に保存する [#vba6c0bc]
- 環境変数 PROMPT_COMMAND に指定されたコマンドがあると、bash はそのコマンドをプロンプトを表示する直前に毎回実行する。
 export PROMPT_COMMAND="history -a; history -r"
- "history -a" は履歴を保存する
- "history -r" は履歴ファイルをリロードする
 shopt -o histappend # histappend は上記により不要になるので、無効にする
- "history -a" :「新しい」履歴行 (bash の現在のセッションの開始以降に入力された履歴行)  を履歴ファイルに追加します。
- "history -c" :全てのエントリを削除し、履歴リストをクリアします。
- "history -r" :履歴ファイルの内容を読み込み、これらを現在の履歴として用います。
- histappend  :設定されている場合、シェルの終了時に変数 HISTFILE の値で指定しているファイルに履歴リストが追加されます。  ファイルへの上書きは行われなくなります。


////////////////////////////////////////////////////////////////////////////////
* 変数 [#jc85b30c]
** 代入 [#jb98a96a]
- 等号の両隣にスペースを入れてはいけない
- 通常の変数
 val=123
- 配列
 array=( 0 1 2 3 )
 array=([0]=0 [3]=3 [1]=1 [2]=2 ) # 配列番号指定。記述は順番通りでなくても良い


** 削除 unset [#r4dc11fd]
 unset val1                # 変数の削除
 unset array[0] array[3]   # 配列から、特定の要素のみを削除
 unset array               # 要素指定無しで配列を指定した場合、その配列全体を削除


** 連番の数値を自動生成する [#se270791]
 $ echo {1..10}
 1 2 3 4 5 6 7 8 9 10
 
 $ echo {10..1}
 10 9 8 7 6 5 4 3 2 1
- 飛び飛びの値の数列を生成したい場合は、 [[seq>Lang/shell/bash#seq]]を使うと良い。


////////////////////////////////////////////////////////////////////////////////
* 特殊変数 [#a73a8fb9]
** 環境変数 [#rec3bc6e]
|~変数 |~意味 |
|$0 |シェル、あるいはプログラムの名前 |
|$1 $2 ... | 引数 |
|$@ |引数の配列 |
|$* |~|
|$# |引数の数 |
|$- |シェルの呼出し時に指定されたオプション |
|$_ |前のコマンドの最後の引数 |
|$! |最後に起動したバックグラウンドジョブのPID |
|$? |最後に実行したコマンドや関数のRETURN値 |
|$$ |そのプロセスのPID |


////////////////////////////////////////////////////////////////////////////////
** その他の特殊変数 [#nead9074]
|~変数 |~意味 |
|${#val[@]} |${val} の長さ(文字列としてみた場合の文字数に相当) |
|${#val} |配列${val[@]} の配列数 |

////////////////////////////////////////////////////////////////////////////////
** 変数と環境変数 [#xc5924ed]
- 定義されている変数を確認するには、set と export が使える。
- export は、環境変数(export されている変数)を表示する
- set は、環境変数に加え、シェル変数も表示する。よって、環境変数を調べるのに使ってはいけない。

////////////////////////////////////////////////////////////////////////////////
* match [#g98339b4]
変数 ${hoge} に対して
|~書法 |~意味 |~備考 |
|${hoge%<ptrn>} |末尾から見て、<ptrn> に最も短く一致する部分を取り除いた値 | |
|${hoge%%<ptrn>} |末尾から見て、<ptrn> に最も長く一致する部分を取り除いた値 | |
|${hoge#<ptrn>} |先頭から見て、<ptrn> に最も短く一致する部分を取り除いた値 | |
|${hoge##<ptrn>} |先頭から見て、<ptrn> に最も長く一致する部分を取り除いた値 | |
|${hoge/<ptrn>/<str>} |${hoge} の値で<ptrn>に最も長く一致する最初の部分だけを<str>で置換する |<ptrn>が # で始まる場合は、hoge の先頭と一致しなければならない&br;<ste>がNULLの場合は、一致した部分が削除される。|
|${hoge//<ptrn>/<str>} |${hoge} の値で<ptrn>に一致する部分全てを<str>で置換する |~|


** 例 [#s0cb59d0]
 FULLPATH=/home/user/file_name.ext
 PATH=${FULLPATH%/*}		# パス部分を表示
 FNAME=${FULLPATH##*/}		# ファイル名以下を表示
 FNAME_ONLY=${FULLPATH%.*}	# ファイル名のみを表示
 DOTEXT=${FULLPATH##*.}		# 拡張子を表示


////////////////////////////////////////////////////////////////////////////////
* 置換演算子 [#fb1828e2]
変数 val に対して
|~書法 |>|~意味 |~備考 |
|~|~val が存在しNULLでない場合 |~左以外の場合 |~|
|${val:-word} |valを返す |wordを返す | |
|${val:=word} |valを返す |valにwordを設定して返す |位置パラメータや特殊なパラメータは除く |
|${val:?msg} |valを返す |val の後にmsgを出力し、現在のコマンド或はスクリプトを中止する(対話型シェルではない場合)&br;msgを省略すると "parameter null or not set" を出力する。 | |
|${val:+word} |wordを返す |NULLを返す | |
|${val:offset} |>|サブ文字を展開する。&br;offsetの位置からlength文字の長さのサブ文字r列をvalから取り出す。&br;文字の位置は0からカウントする。&br;lengthが省略された場合は、offsetからvalの最後までが展開の対象になる。&br;offsetが負値の場合、開始位置はvalの終端からカウントされる。&br;valが@の場合、lengthはoffsetを先頭とする位置パラメータの番号になる。 | |
|${val:offset:length} |~|~| |

////////////////////////////////////////////////////////////////////////////////
* 評価 [#f3207d47]
** 文字列評価 [#o6a8d813]
|~記号 |~意味 |
|-z <string> |<string> の長さが 0 ならば真 |
|-n <string> |<string> の長さが 0 でなければ真 |
|string1 == string2 |文字列が同じならば真。== の代わりに = でも可 |
|tring1 != string2 |2 つの文字列が異なれば真 |
|string1 < string2 |現 在のロケールにおいて、string1 が string2 よりも辞書順で前にある場合に真 |
|string1 > string2 |現在のロケールにおいて、string1 が string2 よりも辞書順で後に ある場合に真 |

*** Cのstrlen() 的使い方をしたいとき [#q8a20d89]
- ${val} の文字列長が0であるか否かによって処理を変える場合は
 if [ -n ${val} ]; then
     処理1
 fi
ではなく、
 if [ ${#val} -gt 0 ]; then
     処理1
 fi
とするとうまくいく。


** ファイル属性 [#a273542e]
|~記号 |~意味 |
|-d <file> |<file>が存在し、且つディレクトリである |
|-e <file> |<file>が存在する |
|-f <file> |<file>が存在し、且つ通常ファイルである |
|-h <file> |<file>が存在し、且つシンボリックリンクである |
|-r <file> |<file>にreadパーミッションが与えられている |
|-s <file> |<file>が存在し、且つ空ではない |
|-w <file> |<file>にwriteパーミッションが与えられている |
|-x <file> |<file>にexecuteパーミッションが与えられている |
|-O <file> |<file>の所有者である |
|-G <file> |<file>のグループIDが自分のものと一致する(複数のグループに属している場合はそのいずれかと一致する) |
|<file1> -nt <file2> |<file1>が<file2>よりも新しい(ファイル変更時刻を比較) |
|<file1> -ot <file2> |<file1>が<file2>よりも古い(ファイル変更時刻を比較) |


** 数値評価 [#rdf1765e]
|~記号 |~意味 |
|arg1 -eq arg2 |arg1 が arg2 に対して等しい |
|arg1 -ne arg2 |arg1 が arg2 に対して等しくない |
|arg1 -lt arg2 |arg1 が arg2 に対して小さい |
|arg1 -le arg2 |arg1 が arg2 に対して小さいか、等しい |
|arg1 -gt arg2 |arg1 が arg2 に対して大きい |
|arg1 -ge arg2 |arg1 が arg2 に対して大きいか、等しい |
※ arg1, arg2 には、正または負の整数を使用出来る。


////////////////////////////////////////////////////////////////////////////////
* フロー制御 [#i2364e5e]
** if [#ne6a73ae]
 if [ 条件式1 ]; then
     処理1
 elif [ 条件式2 ]; then
     処理2
 else
     処理3
 fi
- elif は、C/C++の else if に相当


** for / while [#i9f50ca4]
- for
 for i in "${val_list[@]}"; do
     処理
 
     if [ 次ループへ飛ぶ条件 ]; then
         continue;
     fi
 
     if [ ループ終了条件 ]; then
         break;
     fi
 done
-- val_list: 配列変数。配列全てを表す為、${val_list[@]} と書く。
-- i: 配列 ${val_list[@]} から1要素ずつ代入される為に用意する変数。処理の中ではこのiで取り扱う。変数名は i でなくとも何でも可。for文の中では代入先としての位置づけなので、先頭に変数を表すドル記号($)をつけてはいけない。

-- 自動連番でループを回したい場合は、
 for i in {1..10}; do
     処理
 done
とすれば出来る。但し、上の例の {1..10} はダブルクォートで括ってはいけないので注意!
-- 昇順の自動連番以外で、自動生成した数列(飛び飛び、降順など)でアクセスしたい場合は seq を使用するとよい。

- while
 while [ 条件 ]; do
     処理
 
     if [ 次ループへ飛ぶ条件 ]; then
         continue;
     fi
 
     if [ ループ終了条件 ]; then
         break;
     fi
 done
-- continue, break はfor文同様に使用出来る。

*** 数列の自動生成(seq) を使う [#seq]
- seq は、昇順・降順で番号を自動生成する。
 seq <first_num> [increment_num] <last_num> 
 seq [first_num] <last_num> 
-- first_numが省略された場合のデフォルト値は1
-- increment_num が省略された場合のデフォルト値も1
-- 全ての数値は浮動小数点値として解釈される
-- 詳しくは、 man 1 seq を参照のこと

- 使用例
-- 配列に対し、順次アクセス
 VALS=( a b c d e );
 for i in `seq 0 5`; do    # double-quote で括らないこと!
    echo "val is $VALS[$i]";
 done

-- 配列に対し、逆順にアクセス
 VALS=( a b c d e );
 for i in `seq 5 -1 0`; do    # double-quote で括らないこと!
    echo "val is $VALS[$i]";
 done

-- 配列に対し、飛び飛びにアクセス
 VALS=( a b c d e );
 for i in `seq 0 2`; do    # double-quote で括らないこと!
    echo "val is $VALS[$i]";
 done






- while
 while [ 条件式 ]; do
     処理
 done
-- 条件式が成立する限り、ループを続ける。
-- do キーワード以降は、for文と同じ

** case [#fa3ff88b]
 case ${i} in
 word_1 )
     処理1
     ;;
 word_2 )
     処理2
     ;;
 * )
     上記どの条件にも当てはまらない場合に行う処理
     ;;
 esac
-- ${i} は、評価したい変数(そのときに応じて、名前は何でも可)
-- word_1, word_2,... は、${i} が一致するか否かを調べたいキーワードを記述。
-- C/C++ のswitch-case 等、同等の構文に見られる default に相当するキーワードがないので、default 相当のことをやらせたい場合には、上記のように最後に * の条件文を書いておく。
-- 各処理の最後には、2つの連続したセミコロン(;;)を記述する。これが、C/C++ の場合の break 文に相当する。

////////////////////////////////////////////////////////////////////////////////
* echo の出力先 [#c1d933eb]
- 通常、特に指定しなければ、echo は stdout 若しくは stdout のリダイレクト先へ出力される
- stdout への出力を明示するとき
 $ echo "message" >&1
- stderr へ出力するとき
 $ echo "message" >&2

////////////////////////////////////////////////////////////////////////////////
* printf [#nbeaafe7]
- C/C++ の printf() のように、フォーマット文字列を解釈して出力する

//==============================================================================
** 改行 [#xe04ff81]
- echo と違い、改行したい時は "\n" が必要(echo の場合は -n を付けない限り、終端で自動改行される)
- 渡す引数が文字列の場合は問題ないが、配列である場合は改行文字が思うように機能しないので注意が必要。
- 下記のうち、改行文字が正しく動作するのは (4) のみである。他は表示内容の上にコマンドプロンプトなど、後から表示されるものに一部上書きされたりする。
 (1) A=( "Hello" "world" "\n" );     printf "${A[@]}";
 (2)                                 printf "${A[@]}\n";
 (3) B=( "Hello" "world\n" );        printf "${B[@]}";
 (4) C="Hello world\n";              printf "${C}\n";
- そもそもこういう引数は printf の仕様から見て間違っており、printf の bug ではない。
- 安易に echo と printf は単純な置き換えが出来ない例として示した。
 


////////////////////////////////////////////////////////////////////////////////
* pipe [#q80b142e]
- .bashrc で
 alias llast1='ls -1tr | tail -1'
みたいなことをしている場合に、そのファイルの内容をgrep して別ファイルに保存する場合は、
 $ grep hoge `llast1` | grep -v huga > a.log
とやってもうまくいかない。
 $ cat < `llast1` | grep hoge | grep -v huga | tee a.log
とやればうまくいく。または
 $ ( cat `llast1` | grep hoge | grep -v huga ) | tee a.log
でもうまくいく。


////////////////////////////////////////////////////////////////////////////////
* dot-file だけをリストする [#h40055a6]
- 各種設定ファイル(拡張子しかない、いわゆる dot-file)だけを集めてバックアップしたりする時に...
- "." で始まるファイルをリストする場合は
 $ ls -A | grep ^\\.    # スクリプトに書く場合は、 ^\\. を ^\\\. と書く
&color(red){ここで、 "grep ^\." とすると、"." 以外で始まるファイルもリストされてしまうので注意。};


////////////////////////////////////////////////////////////////////////////////
* Scripts [#d2966a3b]
** llast [#ked8a072]
 #!/bin/bash
 TARGET=${1};
 TARGET_FILE=`ls -1tr | tail -${TARGET} | head -1`
 
 echo ${TARGET_FILE};

** findd [#d228ab40]
 #!/bin/bash
 # find ${@} find -printf "%AY-%Am-%Ad %p\n";    # 最後にアクセスした日付を併記
 find ${@} -printf "%TY-%Tm-%Td %p\n";            # 最後に修正した日付を併記


トップ   新規 一覧 検索 最終更新   ヘルプ   最終更新のRSS