実用的に使えるUNIX技術4選

# 投稿内容
職場でUNIX(シェルスクリプト)を使ったプロジェクトに参加させて頂きました。
参加したプロジェクトで頻繁に使っている技術&教材で学習した技術を投稿していきたいと思います。
UNIXの基礎コマンドの使い方を理解しているとスムーズに読む事が出来ると思います。
理解していない方にも分かりやすく解説していきますが、分からない点が出てくると思いますので、その点はご了承ください。

主に使った技術は
>
1.リダイレクション
2.オプション解析
3.sedコマンド
4.awkコマンド

頻繁に使う4つの技術について紹介していきたいと思います。

ちなみに学習で使った教材は
> 入門UNIXシェルプログラミング
![入門UNIXシェルプログラミング](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/520383/198c7916-5994-836a-7616-6b0b2622fbb3.png)



# 1.リダイレクション
リダイレクションとは入力元や出力元を変える事。(宛先を変える)
この機能を使う事でファイルからデータを入力したり結果をファイルに書き出したりする事が出来ます。

>こんな事に使います
・シェル実行結果をlogファイルに出力したい場合
・HULFT受信したファイルを取り出したい場合
・出力したファイルを使って処理をしたい場合


### 基礎的な書き方
```ruby:基本の書き方
>file          #標準出力をfileというファイルに上書き
>>file         #標準出力をfileというファイルに追加する。
<file          #標準入力をfileというファイルから読み込む
```

```ruby:ファイルディスクリプタを使ったリダイレクション
$echo abcdef 1>file      #標準出力をファイルに上書き
$cat file                #catコマンドでfileの中身を確認
abcdef                   #標準出力した結果が出力されている
$cat file xxx 2>>file2   #標準エラーをfile2に追加書き込み
abcdef                   #標準出力した結果が上書きされて、xxxファイルは存在しないので「No such file or directory」という標準エラーはfile2に追加書き込みされる。
```

| ファイルディスタリプタ | 意味 |
|:-:|:-:|
| 0 | 標準入力(普通はキーボードからの入力)  |
| 1 |  標準出力(普通は端末画面への出力) |
| 2 |  標準エラー(普通は端末画面への出力) |


###　出力結果をゴミ箱に捨てる

```ruby:実行結果をゴミ箱に捨てる場合
$cat file xxx 2>/dev/null   #標準エラーをゴミ箱に捨てる(何もしない)
#「No such file or directory」という標準エラーはゴミ箱に捨てられるので、どこにも表示されない。
```

### readを使ったリダイレクション
readとwhile文を使うと下記の様に応用的に処理を行わせる事が出来ます。
>readはキーボードからの入力をさせる事が出来る。
read LINE
とするとキーボードからの入力をLINEという変数に代入する事が出来る。

```ruby:ファイルから入力処理
#!/bin/bash
while read LINE
do
　・・・・・・・・・・・・・・・
done <file
```
fileから１行読み取りそれをLINEという変数に代入して、doからdoneの間で何らかの処理をさせる事が出来る。

```ruby:ファイルへ出力処理
#!/bin/bash
while read LINE
do
　・・・・・・・・・・・・・・・
done >file
```
キーボードからの入力をLIMEという変数に代入して、doからdoneの間で何らかの処理結果をfileに上書き。

### ネストさせる場合

```ruby:
#!/bin/bash
while read FILENAME
do
  while read LINE
  do
    ・・・・・・
  done < $FILENAME
done <file
```

外側のwhileループはfileから1行ずつ読み込んで処理する。
内側のループは、その読み込んだ行をまたさらに処理する。


# 2.オプション解析(getopts)
コマンドのオプションを解析したりチェックしたりするためのコマンド。

>こんな事に使います
・誤ったオプションを実行させたくない時


```ruby:command_lineファイル

AFLAG=FALSE
BFLAG=FALSE
CFLAG=FALSE
VARUE=
OPT=

#オプション・パラメータの妥当性チェック処理
while getopts abc: OPT
do
  case $OPT in
    a) AFLAG=TRUE ;;
    b) BFLAG=TRUE ;;
    c) CFLAG=TRUE
      VALUE=$OPTARG;;
    \?) echo "Usage: $0 [-ab] [-c VALUE] parameter" 1>&2
          exit 1 ;;
  esac
done

# オプション部分を切り捨てる。
shift `expr $OPTIND - 1`

##オプションチェック結果にて処理分け
if [ "$AFLAG" = "TRUE" ]; then
  echo 'aオプションが指定されました。'
fi

if [ "$BFLAG" = "TRUE" ]; then
  echo 'bオプションが指定されました。 '
fi

if [ "$CFLAG" = "TRUE" ]; then
  echo 'cオプションが指定されました。 '
  echo "→値は"$VALUE"です。" 
fi

```

##### command_lineファイルの実行結果

```ruby:
$./command_line -ab -c xyz
aオプションが指定されました。
bオプションが指定されました。 
cオプションが指定されました。 
→値はxyzです。

$ ./command_line -c xyz -b wwww
bオプションが指定されました。 
cオプションが指定されました。 
→値はxyzです。

$./command_line -ba wwww 
aオプションが指定されました。
bオプションが指定されました。 

$./command_line wwww
#↑↑オプション指定なしだと何も出力せずに終了する。

$./command_line -x 
illegal option -- x
Usage: ./command_line [-ab] [-c VALUE] parameter 
```

getopts コマンドの第一引数にはシェルスクリプトに指定可能なオプションを指定し、さらそのオプションが値を要する場合は : (コロン) を付けます。

上記の例では「$ command -a -b -c "CCC"」といったコマンドラインになる。また、オプションに指定した「“CCC”」などの値は変数 OPTARG に自動的に設定される。

##### shiftコマンドオプション部分を切り捨てる

```ruby:
shift `expr $OPTIND - 1`
```
オプションの他に引数を指定するようなシェルスクリプトの場合、オプション解析終了後に不要となったオプション部分を shift コマンドで切り捨てると以後の引数処理が楽になります。



# 3.sedコマンド
sedコマンドは文字列を指定した文字列に置き換える事が出来る。

>こんな事に使います
・データを加工したい時

```ruby:sedコマンド
#testfile中身のoldtextをnewtextに置き換える
$sed -e "s/oldtext/newtext/" testfile
```

>sedコマンドにつけた-eオプションはその後の文字列が編集用のコマンドという事を表している。
"s/oldtext/newtext/"のｓとは「置換(substitute)」という意味。

上記のコマンドは最初に見つけた文字列しか置き換えてくれないので、全ての文字列を置き換えたい場合は下記のコマンドを実行します。

### 全ての文字列を置き換える
```ruby:全ての文字列を置き換える
#testfileの全てのoldtextをnewtextに置き換える。
sed -e "s/oldtext/newtext/g" testfile
```

```ruby:全ての文字列を削除
#testfileの全てのoldtextを削除する。
$sed -e "s/oldtext//g" testfile
```

### 行頭&行末の文字列を消す

```ruby:行頭の文字列を消す
#行頭にoldtextという文字列があった時にその文字列を削除。
sed -e "s/^oldtext//" 
```
^は「行の最初」を表す。

```ruby:行末の文字列を消す
#行末にoldtextという文字列があった時にその文字列を削除。
sed -e "s/oldtext\$//" 
```

>「^」は行頭
>「$」は行末
「\」はエスケープさせる時


\$は特殊文字なので、/を＄の前に付けてエスケープさせています。

### 文字列の追加

```ruby:行頭に文字列を追加する
#行頭にoldtextという文字列を追加する。
sed -e "s/^/oldtext/" 
```

```ruby:行末に文字列を追加する
#行末にoldtextという文字列を追加する。
sed -e "s/\$/oldtext/" 
```

### 文字列の切り取り

```ruby:文字列の切り取り
#oldtextの文字列以降削除
sed -e "s/oldtext.*//" 
```
oldtextという文字列とそれに続く任意の文字列を削除する事が出来る。

```ruby:文字列の切り取り
#oldtextから始まり、oldtext2で終わる文字列を削除
sed -e "s/oldtext.*oldtext2//"  
```
### タブをスペースに変換

```ruby:
sed -e "s/<tab>/<space>/g" 
```

### 複数のスペースを1個のスペースに変換

```ruby:
sed -e "s/<space><space>*/<space>/g" 
```


### sedコマンドをパイプで繋ぐ
catコマンドでファイルを開いて中身をsedコマンドで置き換えると実用的に使えます。

```ruby:
cat　file |
     sed -e "s/oldtext/newtext/g" |
     while read LINE
     do
      ・・・・・・・・
　　　done 
```

>
「|」はパイプ
左のコマンド結果を右のコマンドに渡している。




# 4.awkコマンド
任意の文字列を取り出す事が出来る。

>こんな事に使います
・ファイルから一部分の文字列を取り出したい時

```ruby:簡単な例
$echo "abc def ghi" | awk '{print $2}'
def

$date | awk '{print $2 $3 $4 $1}'
8月22日土曜日12時51分59秒2020年
```
上記のコマンドは2番目の文字列を$2として取り出している。

## cutコマンドを使う場合
>cutコマンドは文字列から一部を取り出すコマンド。

```ruby:catコマンドを使った例
 #文字列の5番目から7番目の文字列を取り出す
$echo "abc:def:ghi" | cut -c5-7
```
使い方自体はawkコマンドと似ています。