Linuxについて [テキストファイル処理に便利なコマンド]と[viエディタ]

## ファイル処理

### タイムスタンプの処理
タイムスタンプとは最終更新日のことであり、ファイルには必ず存在するもの

~~~
ls -l
~~~
で確認できる

#### touch [オプション] ファイル名
touchコマンド実行によりファイルのタイムスタンプが現在日時に変更される
またファイルが存在しない場合は、中身が空である０バイトのファイルを作成する

* touchオプション

オプション|意味
-|-
-t|ファイルの更新日時を指定する

~~~
例）
$ ls –l hosts.bak
-rv-rw-r—1 okada okada 187 Jun 4 10:06 hosts.bak
$ touch hosts.bak
-rv-rw-r—1 okada okada 187 Jun 5 09:50 hosts.bak
$ touch –t 06030800 hosts.bak
$ ls –l hosts.bak
-rv-rw-r—1 okada okada 187 Jun 3 08:00 hosts.bak
~~~

１段目でhosts.bakファイル情報の確認
３段目で更新時刻の表示
５段目で更新時刻の指定
６段目で変更後の更新時刻の確認

~~~
例）
$ ls –l touched-file
$ touch touched-file
$ ls –l touched-file
-rv-rw-r—1 okada okada 0 Jun 5 09:55 touched-file 
~~~

１段目でtouched-fileファイル情報の確認をするも存在していない
２段目でtouchコマンドによりtouched-fileファイルの作成を行う
３段目でtouched-fileファイルの情報確認を実行
空ファイルなので０バイトになっている



## ファイルの一部の取得
ファイルの先頭や末尾などを一部分見る

#### head [オプション] ファイル名

* 先頭部分を標準出力する
オプションが無い場合は先頭から１０行を標準出力

* ファイル名部分を空白またはハイフンを入れた場合は標準入力からのデータに対して
処理を行う

~~~
例）
$ head FILE
$ cat FILE | head-
$ cat FILE | head
~~~

１段目はFILEの先頭１０行を表示
２，３段目はcatコマンドで閲覧を行い、それに対して先頭１０行を表示

* headオプション

オプション|意味
-|-
-n|先頭から指定した行を標準出力
-c|先頭から指定したバイト分を標準出力


#### tail [オプション] ファイル名
* ファイルの終わり部分を標準出力する
オプションが無い場合は末尾から１０行を標準出力

* ファイル名部分を空白またはハイフンを入れた場合は標準入力からのデータに対して
  処理を行う

~~~
例）
$ tail FILE
$ cat FILE | tail-
$ cat FILE | tail
~~~
１段目はFILEの末尾１０行を表示
２，３段目はcatコマンドで閲覧を行い、それに対して末尾１０行を表示

* tailオプション

オプション|意味
-|-
-n|末尾から指定した行を標準出力
-c|末尾から指定したバイト分を標準出力

~~~
例）
$ tail -n 5 manual-less

      このパッチはLessライセンスの下で配布できる。




                                         Version 358: 08 Jul 2000
LESS(1)
~~~

nオプションを付けて末尾５行を標準出力している



#### tail -f ファイル名

fオプションを付けることにより、変更をリアルタイムでモニタすることが可能
ファイルによっては、その終わり部分が随時変わることがあるので、主にログファイルの
モニタに用いられる

<font color="red">※</font> ログ
サービスの動作状況が出力されるファイルのことで、システムの変更やサービスの動作などで
メッセージがログに記載されると、その内容が出力される


~~~
例）
$ tail -n 5 manual-less





                                         Version 358: 08 Jul 2000
LESS(1)
~~~

ファイルの終わり部分が標準出力される
tail -fはファイルを動的に読み込むことができ、Webサーバーのアクセスログやエラーログを
見る場合に便利なコマンドである


## テキストファイルのソート

テキストファイルの中身をソートする、つまり分類や分別を行う

#### sort [オプション] ファイル名

オプション|意味
-|-
-r|逆順でソート
-k n|n列目のデータをソート
-n|数値としてソート

~~~
例）
$ sort score
keiichi kawazu 70
toru minemura 100
yoshinori oka 85
~~~
オプションをつけない場合は各行の1文字目をアルファベット順（k→t→y）でソートされる

~~~
例）
$ sort -r score
yoshinori oka 85
toru minemura 100
keiichi kawazu 70
~~~
-rオプションでアルファベットの逆順になる

~~~
例）
$ sort -k 2 score
yoshinori oka 85
toru minemura 100
keiichi kawazu 70
~~~
-kオプションを付けると、ソートの鍵として利用する列の番号を指定できる
ここでは名字を鍵として利用したいので２を指定している
なので、2列目の名字の部分を基準にソートされている(k→m→o)

ここに

~~~
$ sort -k 2 -r score
~~~
このように-rもつけると、逆順(o→m→k)となる


### 数値を鍵とする場合の注意

sortは1文字目しかみておらず、アルファベットをソートしたのと同様に、数値も最初の1文字を
見てソートしている**（辞書式ソート）**
なのでこの場合、(1→7→8)の順番となってしまい、数値の大きさが誤って出力されてしまう
そこで数値としてソートする**数値式ソート**により適切な処理を実行する

 ~~~
例）
$ sort -n -k 3 score
keiichi kawazu 70
yoshinori oka 85
toru minemura 100
~~~
sortに-nオプションを付けることで実行できる

~~~
$ sort -n -r -k 3 score
~~~
-rをつけることで逆順にもできる

## 行の重複消去

直前の行と同じ内容があった場合、対象行を出力しない
連続している同じ内容の行を、1行にまとめることができる

#### uniq ファイル名

~~~
例）
$ cat > uniq-sample
AAA
BBB
AAA
CCC
CCC
DDD
~~~
このようなファイルがあったとすると

~~~
例）
$ uniq uniq-sample
AAA
BBB
AAA
CCC
DDD
~~~
重複していたCCCが消えて１行にまとまった
AAAは連続していないので、まとまらない

## 文字の置き換え

標準入力からのデータを文字毎に置き換える(TRanslate)ことができる

#### tr 文字列1 文字列2

~~~
例）
$ cat > translate
Android
iPhone
Windows
Phone
~~~
このようなファイルがあるとすると

~~~
例）
$ cat translate| tr on ON
ANdrOid
iPhONe
WiNdOws
PhONe
~~~
ファイルに含まれるoとnの文字が、大文字のOとNに置き換えられた

#### trの結果をリダイレクトを使い出力
~~~
例）
$ cat translate | tr on ON > translate2 
$ cat translate2
ANdrOid
iPhONe
WiNdOws
PhONe
~~~

translateファイルの文字を置き換えたらリダイレクトコマンドでtranslate2ファイルを作成し内容の
出力、閲覧を実行している


## ファイルの比較

ファイルを比較することができる
主に変更の有無を調べるために実行され、リダイレクトすればファイルに出力することも可能

#### diff[オプション] ファイル1 ファイル2


オプション|意味
-|-
-c|context diff 形式で差分を出力
-n|unified diff 形式で差分を出力





~~~
例）
$ echo "test text" > file1
$ echo "test text" > file2
$ echo "new line" >> file2
~~~
このようなファイルがあるとして


~~~
$ diff file1 file2
1a2
> new line
~~~
オプションを付けずにdiffコマンドを実行した場合は、異なる部分を標準出力される

~~~
$ diff -u file1 file2 
--- file1         2012070611:00:00.098086703+0900
+++ file2         2012070612:00:00.394135769+0900
@@ -1 +1,2 @@
 test text
+new line
~~~

~~~
$ diff -c file1 file2
*** file1         2012070611:00:00.098086703+0900
--- file2         2012070612:00:00.394135769+0900
***************
***1****
---1,2---
  test text
+newline
~~~

オプションを付けてdiffコマンドを実行した場合、ファイルの更新時刻を含めたより多くの差分情報が表示される

### file2の内容を別の文字列で上書き

~~~
$ echo "overwrite text" > file2
（file2を別の文字列で上書き）
$ echo "new line" >> file2
~~~

これでfile1とfile2の共通点はなくなくなったので、
-uコマンドで出力すると

~~~
$ diff -u file1 file2
--- file1          2012070613:21:21.219249366+0900
+++ file2          2012070613:26:51.664814277+0900
@@ -1 +1,2 @@
-test text
+overwrite text
+new line
~~~

diff -uコマンドによる比較は、削除された行の頭にマイナス記号、追加された行にプラス記号が
付加されて標準出力される
標準出力の結果から、file1とfile2の共通していた文字列である「test text」が削除され、
新たに「overwrite test」と「new line」という行が差分追加されている

このようにオプション -uは文字列の増減が激しい、文書やプログラムのソースコードを比較する場合に有用である


## viエディタ

### viエディタとは
Linuxの設定をするためにしばしば利用される
基礎的な操作としてファイルの開閉やテキストの検索や置換、ページ移動や編集などがある

## viの基本操作

#### コマンドモード（viewモード）

ページングによる行やページ単位の移動や、行の削除、コピー、カット、ペーストなどの編集操作を行なうことができる
他にもエディタを開始する方法はviコマンドに続いて編集したいファイルのファイル名を指定することで作業を開始できたり、終了コマンドを実行することでviエディタによる編集作業を終えることができる

#### インサートモード

文字入力を受け付ける


### ファイルを開く コマンド

コマンド|意味
-|-
vi [ファイル名]|ファイルを開く
ESCキーを押して :q|ファイルを閉じる
ESCキーを押して :w|ファイルを保存する
ESCキーを押して :wq|ファイルを保存して終了する
ESCキーを押して :q!|ファイルを保存せず強制的に閉じる


## インサートモードとコマンドモード

viエディタを起動すると、コマンドを入力するコマンドモードでファイルが開かれる
文字列を打ち込むにはiコマンドもしくはaコマンドなどでインサートモードへ切り替えを
実行しなければならない
viコマンドはスクリーンエディタと呼ばれ、基本的にカーソルがある位置に対してコマンドを実行する

### テキストの入力 コマンド

文字を入力するにはインサートモードへ移行
しなければいけない
移行時に入力するコマンドによって、入力位置が変わる

コマンド|意味
-|-
iコマンド(insertコマンド)|カーソルがある位置(文字の前)にテキストを入力する
aコマンド(appendコマンド)|カーソルのある文字の後にテキストを入力する
Iコマンド|行の先頭にテキストを入力する
Aコマンド|行の最後にテキストを入力する

ちなみに文字を間違えたときは「Delete」キーや「BS」キーでカーソルの前の１文字が削除できる

### カーソルの移動 コマンド

テキストファイルを編集していると、入力間違いに気がついたり、後からの変更が出てくるので、既に入力したテキストを修正したい場合は、カーソルを修正したいところへ移動して文字を入力する


コマンド|意味
-|-
h|カーソルを左へ移動
l|カーソルを右へ移動
k|カーソルを上へ移動
j|カーソルを下へ移動
0|カレント行の行頭へ
$|カレント行の行末へ


## 編集中の大きな移動

### ページ単位の移動 コマンド

コマンド|意味
-|-
Ctrl+f|次ページに移動
Ctrl+b|前ページに移動
:10|10行目へ移動
gg|文書頭へ移動
G|文書末へ移動

## 編集操作

### カット・アンド・ペーストのコマンド

コマンド|意味
-|-
x|１文字削除
dd|１行削除
yy|１行コピー
nyy|n行コピー
p|カーソルの文字の次または次の行にペースト
P|カーソルの文字の前または前の行にペースト
u|カット、ペーストを１回取り消し（アンドゥ）


## 置換と検索

テキストファイルの中にある文字列を検索するコマンドを使うと、素早く目的の位置に移動できる
また、置換コマンドを使えば文章中の文字列を探して別の文字列に置き換えることも素早く行なうことができる

### 検索と置換 コマンド

コマンド|意味
-|-
/検索文字列|文字列の検索
n|下方向へ再検索
N|上方向へ再検索
:対象の行 s/検索文字列/置換文字列/オプション|文字列を置換する

/検索文字列 を入力し、「Enter」キーを入力するとカーソルが文字列へ移動

たとえば
CPUを検索するため、「/CPU」を入力するとファイルの中には同じ文字列が複数現れることもある
/コマンドで1回検索した文字列は、nキーを押すと1つ次の文字列を再検索し、Nキーは1つ前の文字列を
再検索する
また、nキーまたはNキーを押した回数だけ再検索できる

文書末まで再検索を行うと、「下まで検索したので上に戻ります」と表示され、もう一度再検索を文書頭から行なうことも可能
文字列を検索すると検索した文字列がハイライト表示され次の文字列を検索するまでハイライト表示が残る
ハイライトを消すには**:nohlsearchコマンド**を実行


### 文字列の置換

viコマンドでは文字の置換を行なうことも簡単で、置換する対象は行範囲を指定することも、文書全体を対象にすることもできる

#### :対象の行s/検索文字列/置換文字列/オプション

#### 置換方法の指定コマンド

コマンド|意味
-|-
:ns/old/new|n行目の最初のoldをnewに置換して終了
:ns/old/new/g|n行目の全てのoldをnewに置換して終了
:%s/old/new/g|ファイル全体の検索語句を置換する
:%s/old/new/gc|置換の度に確認を求める

対象の行を省略すると現在カーソルがある行だけが置換対象となる
オプションにgを指定すると1行にある複数の検索文字列を置換
gを指定しな場合は、行ごとに1回だけ置換を行う


#### 確認しながらファイル全体を文字列置換

gcオプションで確認しながら文字列を置換する場合

たとえば

~~~
lemon ORANGE BANANA *MELON* lemon
ORANGE banana *MELON* lemon ORANGE 
BANANA *MELON* lemon orange banana 
*MELON* lemon orange banana *MELON* 
lemon orange banana *MELON* lemon 
orange banana *MELON* lemon orange
banana *MELON* lemon orange banana
*MELON* lemon orange BANANA *MELON*
~~~
というファイルがあり、

~~~
:%s/lemon/@LEMON@/gc
~~~
を実行すると、

~~~
lemon ORANGE BANANA *MELON* lemon
ORANGE banana *MELON* lemon ORANGE 
BANANA *MELON* lemon orange banana 
*MELON* lemon orange banana *MELON* 
lemon orange banana *MELON* lemon 
orange banana *MELON* lemon orange
banana *MELON* lemon orange banana
*MELON* lemon orange BANANA *MELON*
@LEMON@ に置換しますか? (y/n/a/q/l/^E/^Y)
~~~
確認メッセージが出るが、この時点では置換は実行されない



~~~
@LEMON@ に置換しますか? (y/n/a/q/l/^E/^Y) y
~~~

yと入力すると置換が実行される
そして次のlemonを@ LEMON@に置換するか確認メッセージが出てくる

**y**を入力すると文字列置換して、**n**を入力すると文字列置換しない
該当文字列が見つからなくなるまで、確認メッセージが出続けて、**q**を入力すると、文字列置換を中止できる


>参考書籍

>>『Linux標準教科書 v3.0.2』 LPI-Japan 2019年