Linux - テキスト処理の一般的なツール

# 1. ファイル内容の表示コマンド

## 1.1 テキストファイル内容の表示

### 1.1.1 cat

`cat` コマンドを使うとテキストファイルの内容を表示できます。

```shell
cat [OPTION]... [FILE]...
```

#### よく使われるオプション

- `-E`, `--show-ends` 行末の終了記号`$`を表示
- `-A`, `--show-all` 全ての制御文字を表示
- `-n`, `--number` 表示された各行に行番号を付ける
- `-b`, `--number-nonblank` 空でない行に番号を付ける
- `-s`, `--squeeze-blank` 連続する空行を一行に圧縮

```shell
[root@rocky86 ~]# cat -A /data/fa.txt
a   b$
c $
d^Ib^Ic$
[root@rocky86 ~]# cat /data/fa.txt
a   b
c
d       b       c
[root@rocky86 ~]# cat /data/fb.txt
a
b
c
[root@rocky86 ~]# hexdump -C /data/fb.txt
00000000  61 0d 0a 62 0d 0a 63 0d 0a                       |a..b..c..|
00000009
[root@rocky86 ~]# cat -A /data/fb.txt
a^M$
b^M$
c^M$
[root@rocky86 ~]# file /data/fb.txt
/data/fb.txt: ASCII text, with CRLF line terminators
```

### 1.1.2 nl

行番号を表示します（`cat -b` と似ています）。

```shell
[root@rocky86 ~]# cat /data/f1.txt
a
b
c
d
e
f
g
h
[root@rocky86 ~]# nl /data/f1.txt
     1 a
     2 b
     3 c
     4 d
     5 e
     6 f
     7 g
     8 h
```

### 1.1.3 tac

テキストの内容を逆順で表示します。

```shell
[root@rocky86 ~]# cat /data/fa.txt
1
2
3
4
5
[root@rocky86 ~]# tac /data/fa.txt
5
4
3
2
1
```

例：

```shell
[root@rocky86 ~]# seq 10 | tac
10
9
8
7
6
5
4
3
2
1
```

### 1.1.4 rev

同一行の内容を逆順に表示します。

```shell
[root@rocky86 ~]# cat /data/fa.txt
1 2 3 4 5
a b c
# 逆順に表示する
[root@rocky86 ~]# tac /data/fa.txt
a b c
1 2 3 4 5
# 行ごとに逆順に表示する
[root@rocky86 ~]# rev /data/fa.txt
5 4 3 2 1
c b a
```

## 1.2 ファイル内容をページ毎に表示

### 1.2.1 more

`more` は、ファイルコンテンツをページ表示することができるコマンドです。パイプを使って出力情報をページ分割することも可能です。

#### よく使われるオプション

- `-d` 画面下部にプロンプトを表示
- `-s` 連続空行を圧縮

コマンドオプション:

- スペースキー：ページ送り
- エンターキー：次の行
- `!cmd`: コマンドを実行
- `h`: ヘルプを表示
- `:f`: ファイル名と現在の行番号を表示
- `=`: 行番号を表示

### 1.2.2 less

`less` コマンドはファイルやSTDINの出力をページ分割して表示します。`man` コマンドで使用されるページャーです。

#### よく使われるオプション

- `-e` 表示完了後に自動的に終了
- `-N` 行番号の表示
- `-s` 連続空行を圧縮
- `-S` 長い内容を折り返さずに表示

コマンドオプション:

- `:h` ヘルプを表示
- `/string` 検索
- `:!cmd` コマンドを実行
- `b` 上にスクロール

例:
```shell
[root@rocky86 ~]# less -N /etc/init.d/functions
[root@rocky86 ~]
# tree / -d | less
```

## 1.3 テキストの前または後ろの行内容を表示

### 1.3.1 head

ファイルや標準入力の最初の行を表示します。

#### よく使われるオプション

- `-c`, `--bytes=N` 最初のNバイトを取得
- `-n`, `--lines=N` 最初のN行を取得、Nがマイナスの場合は、ファイルの先頭からN行目まで取得
- `-N` 上述と同じ
- `-q`, `--quiet`, `--silent` ファイル名を出力しない
- `-v`, `--verbose` ファイル名を出力する
- `-z`, `--zero-terminated` NULL文字を行終わりの区切りとする

例：
```shell
[root@centos8 ~]# head -n 3 /etc/passwd
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
```

### 1.3.2 tail

`tail` は `head` とは逆で、ファイルや標準入力の後ろから数えた行を表示します。

#### よく使われるオプション

- `-c`, `--bytes=N` 後ろのNバイトを取得
- `-n`, `--lines=N` 後ろのN行を取得。+Nと記述すると、N行目からファイルの終わりまでを意味します

例：
```shell
[root@centos8 ~]# cat /data/f1.txt
1
2
3
4
5
6
7
8
9
10
[root@centos8 ~]# tail -n 3 /data/f1.txt
8
9
10
```

### 1.3.3 head と tail のまとめ

| コマンド             | 意味                                      | 例                       |
| -------------------- | ----------------------------------------- | ------------------------ |
| `head -n k file`     | `file` の最初の `k` 行を表示              | `head -n 3 /etc/passwd`  |
| `head -n -k file`    | `file` の最初から最後の `k` 行手前までを表示 | `head -n -3 /etc/passwd` |
| `tail -n k file`     | `file` の最後から `k` 行を表示            | `tail -n 3 /etc/passwd`  |
| `tail -n -k file`    | `file` の最後から `k` 行手前までを表示     | `tail -n -3 /etc/passwd` |
| `tail -n +k file`    | `file` の `k` 行目から最後までを表示       | `tail -n +3 /etc/passwd` |

例：6行目のみを表示
```shell
[root@centos8 ~]# seq 20 | head -n 6 | tail -n 1
6
```
```shell
[root@centos8 ~]# seq 20 | tail -n +6 | head -n 1
6
```
# 1.4 `cut` コマンドによるテキストからの特定列の抽出

`cut` コマンドは、テキストファイルや標準入力(STDIN)から特定の列を抽出するために使用されます。デリミタによって分割されたフィールドを処理したり、文字単位やバイト単位でデータを抽出することが可能です。

## 形式

```shell
cut OPTION... [FILE]...
```

### 主なオプション

- `-b|--bytes=LIST`       # バイト単位で列を指定
- `-c|--characters=LIST`  # 文字単位で列を指定
- `-d|--delimiter=DELIM`  # 区切り文字を指定（デフォルトはタブ）
- `-f|--fields=LIST`      # フィールド（列）番号を指定（例: `-f1`, `-f1,2,3`, `-f1-3,4`）
- `-s|--only-delimited`   # 区切り文字で分割された行のみを表示
- `--output-delimiter=STRING` # 出力における区切り文字の代替
- `-z|--zero-terminated`  # 行末記号としてNUL文字を使用（デフォルトは改行文字）

### 使用例

/etc/passwd ファイルからユーザー名、UID、GID、ログインシェルを抽出:
```shell
cut -d: -f1,3-4,7 /etc/passwd
```

ネットワーク設定情報からIPアドレスを抽出:
```shell
ifconfig | head -n2 | tail -n1 | cut -d" " -f10
```

トリミングした後、IPアドレスを抽出:
```shell
ifconfig | head -n2 | tail -n1 | tr -s " " | cut -d " " -f3
```

ディスク使用率から数字のみを抽出:
```shell
df | tr -s ' ' | cut -d' ' -f5 | tr -dc "[0-9\n]"
```

パーセント記号を除いたディスク使用率を抽出:
```shell
df | tr -s ' ' | cut -d' ' -f5 | tr -d '%'
```

特定の文字列の範囲を抽出:
```shell
cut -c2-5 /usr/share/dict/words
```

#### パーティション使用率の計算例

1から10までの数を足し算する:
```shell
echo {1..10} | cut -d ' ' -f1-10 --output-delimiter="+" | bc
```

ディスク使用率を表示（パーセント記号なし・数値のみ）:
```shell
df | tr -s ' ' '%' | cut -d% -f5 | tr -d '[:alpha:]'
```

特定の文字位置のディスク使用率を抽出:
```shell
df | cut -c44-46 | tail -n +2
```

このように、`cut` コマンドはテキストデータを柔軟に処理するためにさまざまなオプションを提供し、シェルスクリプトやコマンドラインでのデータ抽出に便利です。

# 1.5 `paste` コマンドによる複数ファイルの結合

`paste` コマンドは、複数のファイルに存在する同一の行番号の列を一つの行に結合する目的で使用されます。

## 形式

```shell
paste [OPTION]... [FILE]...
```

### よく使用されるオプション

- `-d|--delimiters=LIST` # 区切り文字を指定、デフォルトはタブです
- `-s|--serial` # ファイルを逐一ではなく、シリアルに表示します
- `-z|--zero-terminated` # 行末区切りとしてNUL文字を使用します、通常は改行文字が使用されます

### 例:

```shell
[root@centos8 ~]# cat alpha.log
a
b
c
d
e
f
g
h
[root@centos8 ~]# cat seq.log
1
2
3
4
5
[root@centos8 ~]# paste alpha.log seq.log
a 1
b 2
c 3
d 4
e 5
f 
g 
h
[root@centos8 ~]# paste -d":" alpha.log seq.log
a:1
b:2
c:3
d:4
e:5
f:
g:
h:
[root@centos8 ~]# paste -s seq.log
1 2 3 4 5
[root@centos8 ~]# paste -s alpha.log
a b c d e f g h
[root@centos8 ~]# paste -s alpha.log seq.log
a b c d e f g h
1 2 3 4 5
```

```shell
[root@centos8 ~]# cat title.txt
ceo
coo
cto
[root@centos8 ~]# cat emp.txt
mage
zhang
wang
xu
[root@centos8 ~]# paste title.txt emp.txt
ceo mage
coo zhang
cto wang
 xu
```

ファイル`title.txt`と`emp.txt`を結合して、それぞれの職位と名前が対応するように表示します。

```shell
[root@centos8 ~]# paste -s -d: f1.log f2.log
1:2:3:4:5:6:7:8:9:10
a:b:c:d:e:f:g:h:i:j
```

2つのファイル`f1.log`と`f2.log`を列挙し、それぞれの内容を`:`で区切りながら一行にシリアル表示します。

```shell
[root@centos8 ~]# seq 10 | paste -s -d+ | bc
55
```

1から10までの数字を生成し、これらを`+`で区切って一行に表示し、最後に`bc`コマンドを用いて合計値を計算します。

#### バッチでパスワードを変更する例

```shell
[root@centos8 ~]# cat user.txt
wang
mage
[root@centos8 ~]# cat pass.txt
123456
magedu
[root@centos8 ~]# paste -d: user.txt pass.txt
wang:123456
mage:magedu
[root@centos8 ~]# paste -d: user.txt pass.txt | chpasswd
```

`user.txt`に記載されているユーザー名と`pass.txt`に記載されているパスワードを`paste`コマンドを使い`:で`区切って結合し、`chpasswd`コマンドを通じて一括でパスワードを変更しています。