Bash
Windows
Linux
PowerShell

BASHとPowerShellのフィルタ処理まとめ②

BASHとPowerShellのフィルタ処理例をまとめていきます。下記記事の続きですので、フィルタそのものの説明、目的、検証環境などの前置きは以下記事をご参照ください。

■BASHとPowerShellのフィルタ処理まとめ①

なお今回personal_information03.csvは以下のように編集しています。

personal_information03.csv
連番,氏名,氏名(カタカナ),性別,生年月日,年齢,出身地,血液型
 1,早川哲二,ハヤカワテツジ,男,1996/07/11,21,愛知県,A         BBBB
2,川名来未,カワナクルミ,女,1976/05/15,41,大分県,O
3,村田蒼衣,ムラタアオイ,女,1967/03/27,51,奈良県,A

不要なスペースやタブの処理の話しが多いので2行目の行頭にスペースを1つと行末に複数のスペースと1つのタブを追加しています。可視化すると以下のような感じです。

personal_information03.csv
連番,氏名,氏名(カタカナ),性別,生年月日,年齢,出身地,血液型
<スペース>1,早川哲二,ハヤカワテツジ,男,1996/07/11,21,愛知県,A<複数のスペース><タブ>BBBB
2,川名来未,カワナクルミ,女,1976/05/15,41,大分県,O
3,村田蒼衣,ムラタアオイ,女,1967/03/27,51,奈良県,A

では①に引き続きぽんぽんいきます。

【大文字と小文字を入れ替える】

指定ファイルの全ての大文字を小文字に変えます。
BASHはtr、PowerShell側はTolowerを使用して小文字にしています。

BASH大文字を小文字に入れ替える01
[root@centos74 log]# cat personal_information03.csv | tr '[A-Z]' '[a-z]'
連番,氏名,氏名(カタカナ),性別,生年月日,年齢,出身地,血液型
 1,早川哲二,ハヤカワテツジ,男,1996/07/11,21,愛知県,a         BBBB
2,川名来未,カワナクルミ,女,1976/05/15,41,大分県,o
3,村田蒼衣,ムラタアオイ,女,1967/03/27,51,奈良県,a
PowerShell大文字を小文字に入れ替える01
PS C:\Tools\logs> Get-Content .\personal_information03.csv | foreach { $_.Tolower() }
連番,氏名,氏名(カタカナ),性別,生年月日,年齢,出身地,血液型
 1,早川哲二,ハヤカワテツジ,男,1996/07/11,21,愛知県,a         BBBB
2,川名来未,カワナクルミ,女,1976/05/15,41,大分県,o
3,村田蒼衣,ムラタアオイ,女,1967/03/27,51,奈良県,a

小文字から大文字は以下の通りです。
BASHはtr、PowerShellはToUpperを利用します。

BASH小文字を大文字に入れ替える01
[root@centos74 log]# cat personal_information03.csv | tr '[a-z]' '[A-Z]'
連番,氏名,氏名(カタカナ),性別,生年月日,年齢,出身地,血液型
 1,早川哲二,ハヤカワテツジ,男,1996/07/11,21,愛知県,A         BBBB
2,川名来未,カワナクルミ,女,1976/05/15,41,大分県,O
3,村田蒼衣,ムラタアオイ,女,1967/03/27,51,奈良県,A
PowerShell小文字を大文字に入れ替える01
PS C:\Tools\logs> Get-Content .\personal_information03.csv | foreach { $_.ToUpper() }
連番,氏名,氏名(カタカナ),性別,生年月日,年齢,出身地,血液型
 1,早川哲二,ハヤカワテツジ,男,1996/07/11,21,愛知県,A         BBBB
2,川名来未,カワナクルミ,女,1976/05/15,41,大分県,O
3,村田蒼衣,ムラタアオイ,女,1967/03/27,51,奈良県,A

...ファイルの内容、変わってないんですが許してください。

【区切り文字の変換】

これは想像つくと思いますが、sedやreplaceで置換すればどちらもできます。現在カンマ区切りなのでスペースに変換します。

BASH区切り文字の変換01
[root@centos74 log]# cat personal_information03.csv | sed -e 's/,/ /g'
連番 氏名 氏名(カタカナ) 性別 生年月日 年齢 出身地 血液型
 1 早川哲二 ハヤカワテツジ 男 1996/07/11 21 愛知県 A         BBBB
2 川名来未 カワナクルミ 女 1976/05/15 41 大分県 O
3 村田蒼衣 ムラタアオイ 女 1967/03/27 51 奈良県 A
PowerShell区切り文字の変換01
PS C:\Tools\logs> Get-Content .\personal_information03.csv | foreach { $_ -replace ","," " }
連番 氏名 氏名(カタカナ) 性別 生年月日 年齢 出身地 血液型
 1 早川哲二 ハヤカワテツジ 男 1996/07/11 21 愛知県 A         BBBB
2 川名来未 カワナクルミ 女 1976/05/15 41 大分県 O
3 村田蒼衣 ムラタアオイ 女 1967/03/27 51 奈良県 A

【複数のスペースを1個のスペースに置換】

複数のスペースは*で表現可能です。よって複数のスペースを1個にしてしまうには、以下の通りに書けば良いです。

BASH複数のスペースを1個のスペースに置換01
[root@centos74 log]# cat personal_information03.csv | sed -e 's/  */ /g'
連番,氏名,氏名(カタカナ),性別,生年月日,年齢,出身地,血液型
1,早川哲二,ハヤカワテツジ,男,1996/07/11,21,愛知県,A BBBB
2,川名来未,カワナクルミ,女,1976/05/15,41,大分県,O
3,村田蒼衣,ムラタアオイ,女,1967/03/27,51,奈良県,A
PowerShell複数のスペースを1個のスペースに置換01
PS C:\Tools\logs> Get-Content .\personal_information03.csv | foreach { $_ -replace "  *"," " }
連番,氏名,氏名(カタカナ),性別,生年月日,年齢,出身地,血液型
1,早川哲二,ハヤカワテツジ,男,1996/07/11,21,愛知県,A BBBB
2,川名来未,カワナクルミ,女,1976/05/15,41,大分県,O
3,村田蒼衣,ムラタアオイ,女,1967/03/27,51,奈良県,A

なにかのアプリケーションから出力したファイルは複数スペースに区切られてたりしますがこれで上手く処理することが可能になります。

【ホワイトスペースを1個のスペースに変換】

ホワイトスペースとはタブかスペースのことです。タブが入っているのかスペースが入っているのか分からない時や、タブやスペースが混在している場合に1個のスペースに変えるには以下の通りに変換します。

BASHホワイトスペースを1個のスペースに変換01
[root@centos74 log]# cat personal_information03.csv | sed 's/[ \t][ \t]*/ /g'
連番,氏名,氏名(カタカナ),性別,生年月日,年齢,出身地,血液型
 1,早川哲二,ハヤカワテツジ,男,1996/07/11,21,愛知県,A BBBB
2,川名来未,カワナクルミ,女,1976/05/15,41,大分県,O
3,村田蒼衣,ムラタアオイ,女,1967/03/27,51,奈良県,A
PowerShellホワイトスペースを1個のスペースに変換01
PS C:\Tools\logs> Get-Content .\personal_information03.csv | foreach { $_ -replace "[ \t][ \t]*"," " }
連番,氏名,氏名(カタカナ),性別,生年月日,年齢,出身地,血液型
 1,早川哲二,ハヤカワテツジ,男,1996/07/11,21,愛知県,A BBBB
2,川名来未,カワナクルミ,女,1976/05/15,41,大分県,O
3,村田蒼衣,ムラタアオイ,女,1967/03/27,51,奈良県,A

置換前文字列"[<スペース><タブ>][<スペース><タブ>]*"は鍵括弧を使って「どちらか一方」を表現しています。

またエスケープ文字について補足ですが、通常のエスケープ文字は、BASHはバックスラッシュ(\ )でPowerShellはバッククォート(`)です。これはWindowsのファイルパス表記にバックスラッシュが用いられており、あえてバッククォートがエスケープ文字として採用されたらしいとのことです。

ただし、PoweShellの「正規表現でのエスケープ文字」はBASHと同じくバックスラッシュ(\ )です。これややこしいですが、正しく区別しないとハマってしまう場合があります。-replaceや-matchは正規表現系なのでエスケープ文字は(\ )ですが、-likeはワイルドカード系なのでエスケープ文字は(` )となりますね。PowerShellのエスケープ文字の使い分けの詳細はコメント欄をご参照ください。コメント頂きありがとうございました。

【行頭のホワイトスペースを削除】

行頭にあるスペースあるいはタブを削除する方法です。

行頭のホワイトスペースを削除01
[root@centos74 log]# cat personal_information03.csv | sed 's/^[ ][\t]*//g'
連番,氏名,氏名(カタカナ),性別,生年月日,年齢,出身地,血液型
1,早川哲二,ハヤカワテツジ,男,1996/07/11,21,愛知県,A              BBBB
2,川名来未,カワナクルミ,女,1976/05/15,41,大分県,O
3,村田蒼衣,ムラタアオイ,女,1967/03/27,51,奈良県,A
行頭のホワイトスペースを削除01
PS C:\Tools\logs> Get-Content .\personal_information03.csv | foreach { $_ -replace "^[ ][\t]*","" }
連番,氏名,氏名(カタカナ),性別,生年月日,年齢,出身地,血液型
1,早川哲二,ハヤカワテツジ,男,1996/07/11,21,愛知県,A             BBBB
2,川名来未,カワナクルミ,女,1976/05/15,41,大分県,O
3,村田蒼衣,ムラタアオイ,女,1967/03/27,51,奈良県,A

[<スペース>][<タブ>]*によりタブかスペースで埋めてあっても、削除してくれます。

【行末のホワイトスペースを削除】

行末を意味する$を使って行末のタブやスペースを削除します。以下の通りです。

行末のホワイトスペースを削除01
[root@centos74 log]# cat personal_information03.csv | sed 's/[ ][\t]*$//g'
連番,氏名,氏名(カタカナ),性別,生年月日,年齢,出身地,血液型
 1,早川哲二,ハヤカワテツジ,男,1996/07/11,21,愛知県,A             BBBB
2,川名来未,カワナクルミ,女,1976/05/15,41,大分県,O
3,村田蒼衣,ムラタアオイ,女,1967/03/27,51,奈良県,A
行末のホワイトスペースを削除01
PS C:\Tools\logs> Get-Content .\personal_information03.csv | foreach { $_ -replace "[ ][\t]*`$","" }
連番,氏名,氏名(カタカナ),性別,生年月日,年齢,出身地,血液型
 1,早川哲二,ハヤカワテツジ,男,1996/07/11,21,愛知県,A            BBBB
2,川名来未,カワナクルミ,女,1976/05/15,41,大分県,O
3,村田蒼衣,ムラタアオイ,女,1967/03/27,51,奈良県,A

注意点としてPowerShellはダブルクォートで囲っているので、$をエスケープするようにしてください。BASHのようにシングルクォートで囲っていればエスケープは不要です。

今回は以上です。
これで文字列系の比較は一旦終わって③は「行」の処理をやりたいです。テーマは以下ですね。

 ・文字列指定による行の削除
 ・空白行の削除
 ・行の削除
 ・指定した行の表示
 ・コメント行の削除
 ・キーワードによる行の指定
 ・ファイルを後ろから表示

先の①でも書きましたが次の「行」処理はsedがあるBASHが強い気がします。

今のところどちらもワンライナーで書けているので良いですが、次の「行」処理でPowerShellはワンライナーできないのでは...?と思ってる項目があります。また調べながら書いていきます。

ここまで閲覧頂きありがとうございました。
なにか追加情報や指摘事項、「もっといい方法あるよ!」などありましたらコメントへお願いします。

次の記事は以下です。

■BASHとPowerShellのフィルタ処理まとめ③