Bashでよく使うコマンドまとめ

普段あまり書く機会がなく、いざ書くとき結構忘れているのでまとめておく。

#if
### 基本構文
条件式に指定されたコマンドの終了ステータスを判定し分岐を行う。
終了ステータスが0のときは真、それ以外は偽となる。

```bash

if 条件式1 ; then
  処理1
elif 条件式2 ; then
  処理2
else
  処理3
fi
```
本来条件式の後のthenは次の行に記載するが、
;をつけることで条件式と同一行に記載可能。

また、elseの後はthenは不要であり、
if文を閉じるにはfiが必要。

### 条件式
if文での条件式の評価にはtestコマンドを使用する。
testコマンドは比較の結果を0か1の終了ステータスで返すだけで、
メッセージ出力がないため、評価に特化したコマンドとなる。
```test 引数の条件式```と記載することが可能であるが、
[ 引数の条件式 ]　と省略して記載が可能。
以降は省略形で記載する。
**また、省略時カッコと条件式の間のスペースがマストのため、要注意。**

逆に言うと条件式比較ではtestコマンドを使っているにすぎないので、
testコマンド以外を使うことも可能。


testにおける条件式は文字列の比較と数値の比較で記載方法が異なる。
それぞれ別でまとめる。
#### 数値の比較
num1は条件式左の数字（testコマンドの第一引数）、num2は右（第二引数）である。

| オプション | 数式的意味 | 例 | 何の略か |
|:-----------------:|:------------------:|:------------------:|:------------------:|
| -eq | num1 = num2| 5 -eq 5 | equal |
| -ne | num1 ≠ num2 | 5 -ne 5 | not equal |
| -lt | num1 < num2 | 5 -lt 6 | less than |
| -le | num1 ≦ num2 | 5 -le 6 | less than or equal |
| -gt | num1 > num2 | 5 -gt 4 | greater than |
| -ge | num1 ≧ num2 | 5 -ge 4 | greater than or equal |

```bash

if [ 5 -eq 5 ] ; then
  echo "等しい"
fi
```

#### 文字列の比較
文字列においては、イコールが使用される。
なお、==ではないので注意。

| オプション | 数式的意味 | 例 |
|:-----------------:|:------------------:|:------------------:|
| = | string1 = string2| "hoge" = "fuga" |
| != | string1 ≠ string2| "hoge" != "fuga" |
| -z | string1 = ""(0文字ならば真）  | -z string1 |
| -n | string1 ≠ ""(0文字でなければ真）  | -n string1 |

```bash

if [ "文字" = "文字" ] ; then
  echo "等しい"
fi
```

#### AND,OR条件
AND,OR条件は2つの書き方が可能。
1つ目はtestコマンドのオプションを使って記載する方法
2つ目はbashコマンドを使って記載する方法

##### testコマンドのオプションを使う
testコマンドのオプションなので、
ひとつの[]内に記載が可能。
ただし、ぱっとみでわからないので視認性が下がるかも。

| オプション | 意味 | 例 |
|:-----------------:|:------------------:|:------------------:|
| -a | AND | 5 -a 5 |
| -o | OR | 5 -o 5 |

なお、優先順位は-oのほうが高いため、
```
[ 真 -o 偽 -a 偽 ]
```
の結果は真となる。
()で囲うことでグルーピングが可能だが、
その場合は必ず()をエスケープする必要がある。

##### bashコマンドを使う
条件式内のtest以外のbashコマンドを使用する。
具体的には以下
```コマンド1 && コマンド2```：1つ目の処理が成功した場合のみ、2つ目のコマンドが実行される。
```コマンド1 || コマンド2```：1つ目の処理が失敗した場合のみ、2つ目のコマンドが実行される。

上記のコマンド1と2をtestコマンドに置き換える形である。
```[ 条件式1 ] || [ 条件式2 ]```

なお、こちらの優先順位は前から評価されるため、
```
[ 真 ] || [ 偽 ] && [ 偽 ]
```
は真もしくは偽で真を判定したのち、真かつ偽の判定が実施され、
結果は偽となる。

```
$ [ a = a ] || [ b = bb ]  &&  [ c = cc ]; echo $?
1
```


逆に以下の場合は真である。
```
$ [ a = a ] && [ b = b ]  ||  [ c = cc ]; echo $?
0
```

#### 条件の否定
コマンド前に!をつけることで、
終了ステータスを反転させることが可能。（終了ステータスが0は1に、0以外は0にする）
**！のあとは必ずスペースを入れること。**

```
[ c = cc ]; echo $?
1
! [ c = cc ]; echo $?
0
```
testコマンドの引数でも可能。

```
[ !  c = cc ]; echo $?
0
```

# 配列
普段phpなどを書いていると、
bashの配列で,を使わないことを忘れがちなので一応メモ。

### 定義
空の配列を定義

```bash
array=()
$ echo "${array}"
# 何も表示されない
```
初期値ありの配列を定義

```bash
array=("a" "b" "c")
echo ${array[@]}
a b c
```

##### コマンドの結果を配列に格納
```bash
cd /home/hoge
ls
a.csv b.csv c

dirlist=(`ls -la /home/hoge | grep '*.csv'`)
echo ${dirlist[0]}
a.csv
```


### 値の追加
現在のarrayを入れて再定義するみたいなイメージ

```bash
array=("${array[@]}" "d")
echo ${array[@]}
a b c d
```

### 値の取得
インデックス番号を指定でOK

```bash
echo ${array[0]}
a
```
@で全要素表示

```bash
echo ${array[@]}
a b c d
```

#for
### 基本構文

```bash
for 繰り返し条件; do
    処理
done
```

#### 初期値、ループ条件、ループ時の処理
鉄板パターンも記載可能。

```bash
max=10
for ((i=0; i < $max; i++)); do
    echo $i
done
```

#### ファイルの中身を読み取り

```bash
for i in $(cat filetest.txt ); do
  echo $i
done

1
2
3
4
5
6
7
8
9
```

#### 配列の中身を操作

```bash
array=(0 1 2 3 4 5 6 7 8 9)
for i in ${array[@]}; do
  echo $i
done

0
1
2
3
4
5
6
7
8
9
```


#変数展開
## シングルクォートとダブルクォート
変数などを文字列で展開するためには、
ダブルクォートを使用する。

```bash
echo "${var}"
test
"```
シングルクォートだと展開されないので注意
```bash
echo '${var}'
${var}
```


# mysqlへ接続し、結果をファイル出力
## 基本
セキュリティなどでINTO OUTFILEが使えない場合、
bashからリダイレクトさせて結果を取得する。
Passを変数に入れるとセキュリティ項目の設定次第ではエラーになるので、
その場合は設定を変えるかできないなら都度入力するようにする。
SQLは2行以上記載する場合はインデントを入れるとエラーになるので注意。

結果ファイルはtsv形式で格納される。

```bash

MYSQL_HOST='AAA'
MYSQL_SCHEMA='DBname'
MYSQL_ID='UserName'
OUTPUT_FILE="test.tsv"
SQL="SELECT *
FROM test
Where age > 30 ;"

mysql -h $MYSQL_HOST -u $MYSQL_ID -p -D $MYSQL_SCHEMA > ${OUTPUT_FILE} <<EOF
${SQL}
EOF

```

## 結果を変数に格納
変数=$(コマンド)でコマンドの結果を変数に格納できる。
ただし、横方向に見ながらスペース区切りで挿入されるので、
2カラム以上を抽出する場合は使えなそう。
1カラムだけ取り出してその値をごにょごにょやるとかなら使えそう。

```bash

MYSQL_HOST='AAA'
MYSQL_SCHEMA='DBname'
MYSQL_ID='UserName'
OUTPUT_FILE="test.tsv"
SQL="SELECT *
FROM test
Where age > 30 ;"
RESULT=$(mysql -h $MYSQL_HOST -u $MYSQL_ID -p -D $MYSQL_SCHEMA <<EOF
${SQL}
EOF
)

```

## ヒアドキュメント
文字列をプログラムに埋め込むためのもので、
改行などもそのまま埋め込まれるので、
改行が必要なコマンドや、同じコマンドが連続する際に使用する。

```bash

echo "123"
echo "123"
echo "123"
echo "ABC"
echo "DEF"
echo "GHI"
```
これを

```bash

cat <<EOD
123
456
789
ABC
DEF
GHI
EOD
```
こうできる。

## レコード数の確認方法
```wc -l ファイル名```

## タブ⇒カンマに変換
sedが便利。
grepを組み合わせれば該当フォルダをすべて置換など可能。

```grep -l '\t' ./*.txt | xargs sed -i.bak -e 's/\t/,/1'　```


## 参考
 [if文リファレンス](https://shellscript.sunone.me/if_and_test.html)
 [for一覧](http://www.koikikukan.com/archives/2014/03/03-015555.php)
 [Mysqlの結果を変数へ](http://024minion.hatenablog.jp/entry/2017/07/15/214728)