Macのgrep,sedをBSD版からGNU版に変更する

# 環境
M1Macでやってます。M1Macでは標準でBSD版のgrepとsedが入ってました。

### 確認方法
自分の環境にどちらがインストールされているのかは下記のコマンドで確認できます。BSD版のsedには`--version`オプションが存在しませんが、GNU版には存在します。
```sh 
|*･ω･)っ grep --version
grep (BSD grep, GNU compatible) 2.6.0-FreeBSD
```

```sh 
|*･ω･)っ sed --version
sed: illegal option -- -
```


# GNU版のインストール

## grep 
以下のコマンドを実行します。

```sh 
brew install grep 
```

[brewの公式ページ](https://formulae.brew.sh/formula/grep)を見ても、GNU版がinstallされることが確認できます。  
![スクリーンショット 2023-01-11 9.48.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/965436/d802e8cf-adfc-ab44-ece6-50928cc1849b.png)

インストールが完了すると、以下のような文が出力されています。
```sh 
==> Caveats
==> grep
All commands have been installed with the prefix "g".
If you need to use these commands with their normal names, you
can add a "gnubin" directory to your PATH from your bashrc like:
  PATH="/opt/homebrew/opt/grep/libexec/gnubin:$PATH"
```
prefix（接頭語）にgが付いてインストールされたと書かれています。普通に呼び出したかったら`gnubin`をPATHに追加してねと書かれています。
インストール後特に何もしなければ`ggrep`コマンドとして呼び出すことが可能です。

```sh 
|*･ω･)っ  ggrep --version
ggrep (GNU grep) 3.8
Packaged by Homebrew
Copyright (C) 2022 Free Software Foundation, Inc.
```

## sed 
以下のコマンドを実行します。

```sh
brew install gnu-sed
```

https://formulae.brew.sh/formula/gnu-sed

sedの方はgnuと明記する必要があるようですね。installが完了するとgrepと同じようにprefixとして`g`が付いて`gsed`としてインストールされましたと出力されます。

```sh 
==> Caveats
GNU "sed" has been installed as "gsed".
If you need to use it as "sed", you can add a "gnubin" directory
to your PATH from your bashrc like:

    PATH="/opt/homebrew/opt/gnu-sed/libexec/gnubin:$PATH"
```

こちらもgsedとして呼び出すことができるようになっています。

```sh 
|*･ω･)っ  gsed --version
gsed (GNU sed) 4.9
Copyright (C) 2022 Free Software Foundation, Inc.
```


# 使い方

## BSD版との違い

### grep
例えば、grepなら、GNU版で後方参照ができるようになります。後方参照というのは()で囲った正規表現でマッチした部分を\1とか\2で参照（呼び出し）できるようになる機能のことです。

以下の文章のように、コピペミスなどで2回連続になってしまっている部分を抜き出したい際などに使えます。
```sh 
|*･ω･)っ cat diarydiary.txt
私は私は今、オーストラリアに
いるのですが、特に観光もせず、
部屋でシェル芸シェル芸の問題
問題を考えていますす。人それ
ぞれ、人生いろいろですよね。
```

```sh 
|*･ω･)っ cat diarydiary.txt | ggrep -oE '(.+)\1'
私は私は
シェル芸シェル芸
すす
いろいろ
```

BSD版のgrepだと後方参照が機能してくれません。。。
```sh 
|*･ω･)っ cat diarydiary.txt | grep -oE '(.+)\1'

```

- **参考**
    - [1日1問、半年以内に習得 シェル・ワンライナー160本ノック](https://gihyo.jp/book/2021/978-4-297-12267-6)
        - `diarydiary.txt`は上記書籍の一部問題で使用されているものです。

### sed
あとは、sedでは-zオプションが使えたりします（複数行ある文字列などの置換を行いたい場合に、改行をまたいで検索することができるようになります）。BSD版には-zオプションはありません。

```sh 
|*･ω･)っ gsed --help | grep -3 -- -z
  -u, --unbuffered
                 load minimal amounts of data from the input files and flush
                 the output buffers more often
  -z, --null-data
                 separate lines by NUL characters
      --help     display this help and exit
      --version  output version information and exit
```

## 実行速度を計測
せっかくなので速度検証もしてみます。
こんなコマンドでどっちが速いのか計測してみました。適当な数字をgrep1000回やってもらいます。

```sh 
|*･ω･)っ  time (for i in {0..1000}; do echo $i | ggrep '[0-9]*' > /dev/null; done)
```

### BSD版grep 
```sh 
|*･ω･)っ  time (for i in {0..1000}; do echo $i | ggrep '[0-9]*' > /dev/null; done)
( for i in {0..1000}; do; echo $i | grep '[0-9]*' > /dev/null; done; )  
0.28s user 1.01s system 84% cpu 1.516 total
```

### GNU版grep
```sh 
|*･ω･)っ  time (for i in {0..1000}; do echo $i | ggrep '[0-9]*' > /dev/null; done)
( for i in {0..1000}; do; echo $i | ggrep '[0-9]*' > /dev/null; done; )  
0.63s user 1.07s system 88% cpu 1.915 total
```

あれ、GNU版の方が全体的に遅いですね...
速度だけで言ったらBSD版の方が有利なのかな、zshとの相性もあるのかも？
とはいえ、機能的にはGNU版の方が充実しているので、これくらいの速度差であればとりあえずGNU版を使っておいたら良いのではと思います。




# 付録：そもそもBSDとGNUとは？
どちらも長い歴史があります。調べていったらとても奥深いのでここでは概要とリンクだけ載せます。

## BSDとは

https://docs.freebsd.org/ja/books/handbook/introduction/#history

Berkeley Software Distributionの略で、カルフォルニア大学バークレー校で開発されたUNIX互換のOSや、ソフトウェア群のこと。最初に一般向けに配布が開始されたのが1993年頃。

## GNUとは

https://www.gnu.org/gnu/about-gnu.en.html

1983 年に Richard Stallman (rms) によって開発された、すべてのソフトウェアユーザーが自由にコンピューティングを制御できることを目指したオペレーティングシステム、またはソフトウェア群。それらを開発するプロジェクトのことをGNUプロジェクトと呼んでいる。