初心者向けPerlワンライナー入門:厳選サンプル30選


初心者向けPerlワンライナー入門:厳選サンプル30選

テキスト処理やシステム管理のタスクを効率化したいと思ったことはありませんか? そんなときに強力な味方となるのが、Perlの「ワンライナー」です。コマンドラインから短いコードを実行するだけで、ファイルの内容を操作したり、特定の情報を抽出したり、データを整形したりといった様々な処理が瞬時に行えます。

Perlワンライナーは、grepsedawkといった定番のコマンドラインツールと似た用途で使われますが、Perlの持つ強力な正規表現能力、豊富な組み込み関数、柔軟なデータ構造を活用できるため、より複雑で洗練された処理を記述することが可能です。

この記事では、Perlワンライナーの基本的な使い方から始め、特に初心者が覚えておくと役立つ厳選された30のサンプルを通して、その強力さと便利さを体験していただきます。各サンプルについて、その目的、コマンド、入力例、出力例、そして詳細な解説を行います。

この記事を読み終える頃には、Perlワンライナーがあなたのコマンドラインツールキットに欠かせない存在になっているはずです。

1章:Perlワンライナーとは? なぜ使うのか?

Perlワンライナーとは

Perlワンライナーは、その名の通り、コマンドライン上で一行(または非常に短いコード)で完結するPerlプログラムです。通常、perlコマンドの-eオプションを使用して、その後にPerlのコードを文字列として直接記述します。

例:
bash
$ perl -e 'print "Hello, World!\n";'
Hello, World!

これは非常にシンプルな例ですが、Perlワンライナーは通常、ファイルや標準入力からテキストを受け取り、それを処理して標準出力に結果を出力するという形で利用されます。

なぜPerlワンライナーを使うのか?

  1. 強力なテキスト処理能力: Perlはもともとテキスト処理に特化した言語として発展しました。正規表現の扱いに非常に長けており、複雑なパターンマッチングや置換を簡単に行えます。
  2. 柔軟性と表現力: grepsedawkといった特定の機能に特化したツールと異なり、Perlは汎用プログラミング言語です。ワンライナーの中でも、条件分岐、ループ、配列、ハッシュといったPerlの言語機能を活用できるため、より複雑なロジックやデータ構造を用いた処理が可能です。
  3. 効率: 短いタスクであれば、ファイルを作成してスクリプトを書くよりも、ワンライナーとして直接実行する方が効率的です。
  4. 既存ツールの代替・連携: grep -v, sed 's/old/new/g', awk '{print $1}'といった基本的なコマンドライン操作は、Perlワンライナーで代替または組み合わせて使うことができます。

2章:Perlワンライナーの基本オプション

Perlワンライナーを記述する上で、頻繁に使用されるコマンドラインオプションがいくつかあります。これらを理解することが、ワンライナーマスターへの第一歩です。

  • -e 'code'

    • このオプションは、コマンドライン引数として渡された文字列をPerlコードとして実行します。ワンライナーの心臓部です。
    • 複数の-eオプションを指定することで、複数のコードブロックを実行できます。これらは指定された順序で実行されます。
    • 例:perl -e 'print "First ";' -e 'print "Second\n";'
  • -n

    • このオプションを指定すると、Perlは入力(ファイルまたは標準入力)を一行ずつ読み込み、その各行に対して-eで指定されたコードを実行するループを暗黙的に生成します。
    • 各行は特殊変数$_に格納されます。
    • 注意点: -nはデフォルトでは各行を自動的に出力しません。出力するには明示的にprintなどを使用する必要があります。
    • これはwhile (<>) { ... }というループを-eで指定したコードの前後に付けてくれるイメージです。
  • -p

    • -nと同様に、入力を行ごとに読み込み、-eで指定されたコードを実行するループを生成します。
    • 重要な違い: -pは、各行の処理が終了した後に、その行の内容($_に格納されている値)を自動的に標準出力に出力します。
    • これはwhile (<>) { ...; print }というループを付けてくれるイメージです。行を加工して出力する場合に非常に便利です。
  • -a

    • このオプションは、-nまたは-pと組み合わせて使用されることがほとんどです。
    • 入力の各行を自動的に分割(split)し、その要素を特殊変数@Fという配列に格納します。
    • デフォルトの区切り文字は連続する空白文字(スペース、タブなど)です。これはawkのデフォルトの挙動に似ています。
    • @Fのインデックスは0から始まります。$F[0]は最初のフィールド、$F[1]は2番目のフィールドです。
    • 例:行がapple orange bananaであれば、@F("apple", "orange", "banana")となります。
  • -F/pattern/

    • -aオプションを使用する際に、行を分割するための区切り文字(パターン)を指定します。
    • /pattern/の部分には、正規表現または単純な文字列を指定できます。
    • 例:-F/[:,]/\s*は、カンマ(,)またはコロン(:)の後に0個以上の空白が続くパターンで分割します。-F,はカンマ1文字で分割します。-F''は1文字ずつ分割します。
  • -i[.bak]

    • このオプションは「インプレース編集(in-place editing)」を行います。つまり、入力ファイルを読み込み、処理した結果を元のファイルに上書きします。
    • バックアップをとりたい場合は、拡張子を指定します。例:-i.bakとすると、元のファイルは.bakという拡張子が付いたファイルとして保存されます。
    • バックアップが不要な場合は、拡張子を付けずに-iとだけ指定します。
    • 非常に便利なオプションですが、元のファイルが変更されるため注意が必要です。
  • -l

    • このオプションには2つの働きがあります。
      1. 入力から読み込む各行の末尾にある改行文字(\n)を自動的に削除します(chomp関数と同じ働き)。
      2. print関数を実行する際に、引数の末尾に自動的に改行文字を追加します。これは、-n-pのどちらと組み合わせるかによって挙動が異なります。
        • -pと組み合わせた場合: print$_を自動的に出力する前に実行されます。-lprintに改行を付け加えます。しかし、-p自身が最後に$_chompされた後の改行なしの行)に改行を付けて出力しようとします。結果として、-p -lの場合は、-lの改行追加の機能はあまり目立たず、$_chompされる効果が主になります。
        • -nと組み合わせた場合: printは明示的に呼び出す必要があります。-lは、その明示的なprintの出力に改行を付け加えてくれます。つまり、print "something"print "something\n"のように働きます。これは非常に便利です。

これらのオプションは組み合わせて使用することで、様々な複雑なタスクを簡潔に記述できるようになります。

3章:厳選サンプル30選

それでは、これらの基本オプションとPerlの基本的な構文を使った、実践的なワンライナーのサンプルを30個紹介します。

カテゴリ1:表示と抽出 (Printing & Filtering)

ここでは、入力データの中から特定の行やフィールドを表示するワンライナーを紹介します。主に-nオプションが活躍します。

サンプル1:全ての行を表示する

bash
$ perl -n -e 'print;' file.txt

* 目的: ファイルの内容をそのまま表示します。これはcat file.txtと同じ結果になりますが、Perlワンライナーの基本的な構造を示す例です。
* コマンド: perl -n -e 'print;' file.txt
* 入力例 (file.txt):
Line 1
Line 2
Line 3

* 出力例:
Line 1
Line 2
Line 3

* 解説:
* perl: Perlインタプリタを実行します。
* -n: 入力を一行ずつ読み込み、-eのコードを実行するループを生成します。各行は$_に格納されます。各行の処理後に自動的な出力は行いません。
* -e 'print;': $_の内容を標準出力に出力します。-nは自動出力しないため、明示的にprintが必要です。;は文の区切りです。
* file.txt: 処理対象のファイルです。

サンプル2:指定したパターンを含む行を表示する

bash
$ perl -n -e 'print if /pattern/;' file.txt

* 目的: grep 'pattern' file.txt と同じ処理を行います。特定のパターンを含む行のみを表示します。
* コマンド: perl -n -e 'print if /pattern/;' file.txt
* 入力例 (file.txt):
apple pie
banana split
cherry pie
date bar

* 出力例 (pattern=”pie”):
apple pie
cherry pie

* 解説:
* -n: 各行を$_に読み込みます。
* /pattern/: これは$_ =~ /pattern/の省略形です。$_が指定した正規表現パターンにマッチするかどうかをテストします。
* print if /pattern/;: /pattern/$_がパターンにマッチするかどうか)が真の場合にのみ、printを実行します。Perlでは、条件式の後にブロックなしで単一のステートメントを置くことで、後置if文として記述できます。

サンプル3:指定したパターンを含まない行を表示する

bash
$ perl -n -e 'print unless /pattern/;' file.txt

* 目的: grep -v 'pattern' file.txt と同じ処理を行います。特定のパターンを含まない行のみを表示します。
* コマンド: perl -n -e 'print unless /pattern/;' file.txt
* 入力例 (file.txt):
apple pie
banana split
cherry pie
date bar

* 出力例 (pattern=”pie”):
banana split
date bar

* 解説:
* -n: 各行を$_に読み込みます。
* /pattern/: $_がパターンにマッチするかどうかをテストします。
* print unless /pattern/;: /pattern/が偽($_がパターンにマッチしない)の場合にのみ、printを実行します。unlessif notと同じ意味を持つ制御構造です。

サンプル4:空行を表示しない

bash
$ perl -n -e 'print if /\S/;' file.txt

* 目的: 空行(空白文字やタブのみの行を含む)以外の行を表示します。
* コマンド: perl -n -e 'print if /\S/;' file.txt
* 入力例 (file.txt):
“`
Line 1

Line 2

    Line 4 (indent)
```
  • 出力例:
    Line 1
    Line 2
    Line 4 (indent)
  • 解説:
    • -n: 各行を$_に読み込みます。
    • /\S/: 正規表現\Sは「空白文字ではない文字」にマッチします。したがって、/\S/は行の中に一つでも空白文字ではない文字が含まれているかどうかをテストします。空行や空白文字だけの行はこれにマッチしません。
    • print if /\S/;: 行に非空白文字が含まれている場合のみprintを実行します。

サンプル5:行番号を付けて表示する

bash
$ perl -n -e 'print "$.: $_";' file.txt

* 目的: 各行の先頭に行番号を付けて表示します。cat -n file.txtに似ています。
* コマンド: perl -n -e 'print "$.: $_";' file.txt
* 入力例 (file.txt):
First line.
Second line.
Third line.

* 出力例:
1: First line.
2: Second line.
3: Third line.

* 解説:
* -n: 各行を$_に読み込みます。
* $.: Perlの特殊変数で、現在の入力行の行番号を保持しています。最初の行は1です。
* print "$.: $_";: ダブルクォート文字列内では、変数($., $_)は展開されます。行番号、コロンとスペース、そして現在の行の内容($_)を連結して出力しています。-nなので明示的なprintが必要です。

サンプル6:特定の行番号の範囲を表示する

bash
$ perl -n -e 'print if 5 .. 10;' file.txt

* 目的: ファイルの5行目から10行目までを表示します。これはsed -n '5,10p' file.txtに似ています。
* コマンド: perl -n -e 'print if 5 .. 10;' file.txt
* 入力例 (file.txt): (15行のファイルと仮定)
Line 1
...
Line 5
Line 6
...
Line 10
...
Line 15

* 出力例:
Line 5
Line 6
...
Line 10

* 解説:
* -n: 各行を$_に読み込み、$.を行番号として管理します。
* 5 .. 10: Perlの「範囲演算子(range operator)」です。スカラーコンテキスト(ここではifの条件式)で使用されると、左側の式(5)が真になった行から、右側の式(10)が真になる行まで、論理値の真を返します。ここでは、$. == 5が真になった行から$. == 10が真になる行までが範囲となります。
* print if 5 .. 10;: 範囲演算子が真を返す行(5行目から10行目)でのみprintを実行します。

サンプル7:指定したフィールド(列)を表示する(空白区切り)

bash
$ perl -a -n -e 'print $F[0];' file.txt # 1列目
$ perl -a -n -e 'print $F[1];' file.txt # 2列目
$ perl -a -n -e 'print "$F[0] $F[2]";' file.txt # 1列目と3列目

* 目的: 空白文字で区切られたデータから、特定の列(フィールド)を抽出して表示します。awk '{print $1}' file.txtに似ています。
* コマンド: 上記参照
* 入力例 (file.txt):
apple 1.0 red
banana 0.5 yellow
cherry 2.0 red

* 出力例 (print $F[0]):
apple
banana
cherry

* 出力例 (print "$F[0] $F[2]"):
apple red
banana yellow
cherry red

* 解説:
* -a: 入力行を自動的に分割し、@F配列に格納します。デフォルトでは連続する空白で分割されます。
* -n: 各行を処理するループを生成します。
* @F: 分割されたフィールドを保持する配列です。$F[0]が最初のフィールド、$F[1]が2番目、などとなります。
* print $F[0];: 最初のフィールド($F[0])を出力します。-nのため明示的なprintが必要です。改行は自動で付かないので、各フィールドが改行されずに繋がって出力されます。
* print "$F[0] $F[2]";: 1番目のフィールドと3番目のフィールドをスペースで区切って出力します。"$F[0] $F[2]\n"のように改行を明示的に加えるか、後述の-lオプションを使うと、フィールドごとに改行されて見やすくなります。

サンプル8:指定したフィールドを表示する(カンマ区切り)

bash
$ perl -F, -a -n -e 'print $F[1];' file.csv

* 目的: カンマ(,)で区切られたCSV形式のデータから、特定の列(フィールド)を抽出して表示します。
* コマンド: perl -F, -a -n -e 'print $F[1];' file.csv
* 入力例 (file.csv):
id,name,value
1,apple,100
2,banana,200
3,cherry,150

* 出力例:
name
apple
banana
cherry

* 解説:
* -F,: -aオプションの区切り文字をカンマ(,)に指定します。
* -a, -n: 入力行をカンマで分割して@Fに格納し、各行を処理します。
* print $F[1];: 2番目のフィールド(インデックス1)を出力します。

サンプル9:各行の文字数を表示する

bash
$ perl -n -e 'print length($_);' file.txt

* 目的: 各行の文字数を計算して表示します。
* コマンド: perl -n -e 'print length($_);' file.txt
* 入力例 (file.txt):
hello
world!
Perl

* 出力例:
5
6
4

* 解説:
* -n: 各行を$_に読み込みます。
* length($_): Perlの組み込み関数lengthは、引数(ここでは現在の行$_)の文字列の長さを返します。
* print length($_);: 計算された長さを出力します。-nのため明示的なprintが必要です。出力後に改行はつきません。

サンプル10:ファイルを逆順に表示する(簡易版)

bash
$ perl -n -e 'unshift @lines, $_;' -e 'END { print @lines; }' file.txt

* 目的: ファイルの内容を逆順(最終行から最初の行へ)で表示します。tac file.txtに似ています。ただし、ファイルを全てメモリに読み込むため、大きなファイルには向きません。
* コマンド: perl -n -e 'unshift @lines, $_;' -e 'END { print @lines; }' file.txt
* 入力例 (file.txt):
Line 1
Line 2
Line 3

* 出力例:
Line 3Line 2Line 1
* 解説:
* -n: 各行を$_に読み込みます。
* -e 'unshift @lines, $_;': 最初の-eブロックです。Perlのスクリプトは複数の-eブロックを連結して実行します。
* @lines: linesという名前の配列です。Perlでは宣言なしで配列を使用できます。
* unshift @lines, $_: unshift関数は、配列の先頭に要素を追加します。各行($_)が読み込まれるたびに、@lines配列の先頭に追加されていきます。これにより、配列には行が逆順に格納されます。
* -e 'END { print @lines; }': 2番目の-eブロックです。
* END { ... }: Perlの特殊なブロックです。入力ファイルの処理が全て終わった後(スクリプトが終了する直前)に一度だけ実行されます。
* print @lines;: ENDブロック内で、蓄積された@lines配列の内容を全て出力します。配列をprintに渡すと、その要素が連結されて出力されます。デフォルトでは要素間に区切り文字は入りません(後述の-lまたは$"="\n"などを使うと改行されます)。

カテゴリ2:置換と加工 (Substitution & Transformation)

入力データの各行の内容を変換したり、一部を削除したりするワンライナーです。主に-pオプションと正規表現の置換オペレータs///が活躍します。

サンプル11:全ての行の「foo」を「bar」に置換する

bash
$ perl -p -e 's/foo/bar/g;' file.txt

* 目的: ファイル内の各行に現れる全ての「foo」という文字列を「bar」に置換します。これはsed 's/foo/bar/g' file.txtと同じ処理です。
* コマンド: perl -p -e 's/foo/bar/g;' file.txt
* 入力例 (file.txt):
foo bar baz foo
another line with foo
no match here

* 出力例:
bar bar baz bar
another line with bar
no match here

* 解説:
* -p: 入力を一行ずつ読み込み、-eのコードを実行し、処理後の行の内容($_)を自動的に出力します。
* -e 's/foo/bar/g;': 各行に対してこのコードが実行されます。
* s/pattern/replacement/: Perlの正規表現置換オペレータです。現在のデフォルト変数$_に対して、patternにマッチする部分をreplacementで置換します。
* foo: 検索するリテラル文字列(パターン)です。
* bar: 置換後の文字列です。
* g: フラグです。gは「グローバル(global)」を意味し、行内でマッチする全ての箇所を置換します。このフラグがないと、最初に見つかった一つだけが置換されます。
* 処理後の$_-pによって自動的に出力されます。

サンプル12:行頭の空白を削除する

bash
$ perl -p -e 's/^\s+//;' file.txt

* 目的: 各行の先頭にある空白文字(スペース、タブなど)を全て削除します。
* コマンド: perl -p -e 's/^\s+//;' file.txt
* 入力例 (file.txt):
Indented line 1
Another indented line
Normal line

* 出力例:
Indented line 1
Another indented line
Normal line

* 解説:
* -p: 入力行を処理後、自動出力します。
* s/^\s+//;:
* ^: 正規表現のアンカーで、行の先頭にマッチします。
* \s: 空白文字(スペース、タブ、改行など)にマッチします。
* +: 直前の要素(\s)が1回以上繰り返される場合にマッチします。つまり、1つ以上の空白文字にマッチします。
* ^\s+: 行の先頭にある1つ以上の空白文字の連続にマッチします。
* 置換後の文字列は空(//の間が空)なので、マッチした空白文字は削除されます。gフラグは必要ありません、行頭の空白は一度しか出現しないためです。

サンプル13:行末の空白を削除する

bash
$ perl -p -e 's/\s+$//;' file.txt

* 目的: 各行の末尾にある空白文字を全て削除します。chompと組み合わせて使われることが多いですが、chompは改行しか削除しないのに対し、これは任意の末尾空白を削除できます。
* コマンド: perl -p -e 's/\s+$//;' file.txt
* 入力例 (file.txt):
Line with spaces at end
Another line
No spaces here

* 出力例:
Line with spaces at end
Another line
No spaces here

* 解説:
* -p: 入力行を処理後、自動出力します。
* s/\s+$//;:
* \s+: 1つ以上の空白文字にマッチします。
* $: 正規表現のアンカーで、行の末尾にマッチします。
* \s+$: 行の末尾にある1つ以上の空白文字の連続にマッチします。
* 置換後の文字列は空なので、マッチした末尾空白は削除されます。

サンプル14:行頭・行末の空白を両方削除する

bash
$ perl -p -e 's/^\s+|\s+$//g;' file.txt

* 目的: 各行の先頭と末尾の両方の空白文字を削除します。
* コマンド: perl -p -e 's/^\s+|\s+$//g;' file.txt
* 入力例 (file.txt):
Indented line with spaces
Another one
Normal line

* 出力例:
Indented line with spaces
Another one
Normal line

* 解説:
* -p: 入力行を処理後、自動出力します。
* s/^\s+|\s+$//g;:
* |: 正規表現のOR演算子です。左辺^\s+または右辺\s+$のどちらかにマッチすれば良いことを意味します。
* ^\s+: 行頭の空白にマッチします。
* \s+$: 行末の空白にマッチします。
* /g: グローバルフラグです。これにより、行頭の空白(左辺にマッチ)と行末の空白(右辺にマッチ)の両方が存在する場合でも、両方が置換(削除)されます。gフラグがないと、最初に見つかった方だけが削除されます。

サンプル15:連続する空白を1つのスペースに置換する

bash
$ perl -p -e 's/\s+/ /g;' file.txt

* 目的: 連続する1つ以上の空白文字を、1つのスペースに置換します。
* コマンド: perl -p -e 's/\s+/ /g;' file.txt
* 入力例 (file.txt):
This has many spaces.
Another test.

* 出力例:
This has many spaces.
Another test.

* 解説:
* -p: 入力行を処理後、自動出力します。
* s/\s+/ /g;:
* \s+: 1つ以上の空白文字の連続にマッチします。
* / /: マッチした部分(連続する空白)を1つのスペースに置換します。
* /g: 行内でマッチする全ての連続空白に対して置換を行います。

サンプル16:空行を削除する

bash
$ perl -n -e 'print if /\S/;' file.txt

* 目的: サンプル4と同じです。空行や空白のみの行を削除して表示します。再掲ですが、加工系の文脈でも重要なのでここに含めます。
* コマンド: perl -n -e 'print if /\S/;' file.txt
* 解説: サンプル4を参照。-nで読み込み、非空白文字が含まれる行だけをprintしています。

サンプル17:行全体を削除する(パターンを含む行)

bash
$ perl -n -e 'print unless /pattern/;' file.txt

* 目的: サンプル3と同じです。特定のパターンを含む行全体を削除して表示します。これも加工系の文脈で重要なので再掲します。
* コマンド: perl -n -e 'print unless /pattern/;' file.txt
* 解説: サンプル3を参照。-nで読み込み、パターンを含まない行だけをprintしています。

サンプル18:行全体を削除する(パターンを含まない行)

bash
$ perl -n -e 'print if /pattern/;' file.txt

* 目的: サンプル2と同じです。特定のパターンを含む行だけを残し、それ以外の行(パターンを含まない行)を削除して表示します。これも再掲。
* コマンド: perl -n -e 'print if /pattern/;' file.txt
* 解説: サンプル2を参照。-nで読み込み、パターンを含む行だけをprintしています。

サンプル19:特定の列(フィールド)を削除する(空白区切り)

bash
$ perl -a -p -l -e 'splice @F, 1, 1;' -e '$_ = join " ", @F;' file.txt

* 目的: 空白区切りのデータから、2番目の列(インデックス1)を削除します。
* コマンド: perl -a -p -l -e 'splice @F, 1, 1;' -e '$_ = join " ", @F;' file.txt
* 入力例 (file.txt):
apple 1.0 red
banana 0.5 yellow
cherry 2.0 red

* 出力例:
apple red
banana yellow
cherry red

* 解説:
* -a: 入力行を@Fに分割します。
* -p: 各行を処理し、最後に$_の内容を自動出力します。
* -l: 入力行の改行を削除(chomp)し、print時に改行を自動追加します。-pと組み合わせると、$_がchompされ、自動出力時に改行が追加される効果があります。
* -e 'splice @F, 1, 1;': 最初の-eブロックです。
* splice @F, 1, 1: Perlの組み込み関数spliceは、配列の一部を操作します。ここでは@F配列のインデックス1から1つの要素を削除しています。これで2番目のフィールドが削除されます。
* -e '$_ = join " ", @F;': 2番目の-eブロックです。
* join " ", @F: @F配列の要素を、指定した区切り文字(ここではスペース " ")で連結して一つの文字列にします。
* $_ = ...;: 連結した文字列を$_に戻します。-pは処理後の$_を出力するため、これで期待する出力が得られます。

サンプル20:文字のエンコーディングを変換する(UTF-8 to Shift-JIS)

bash
$ perl -MEncode -p -e '$_ = encode("Shift JIS", decode("UTF-8", $_));' utf8_file.txt > sjis_file.txt

* 目的: UTF-8エンコーディングのファイルを読み込み、Shift-JISに変換して別ファイルに出力します。エンコーディング変換にはEncodeモジュールを使用します。
* コマンド: perl -MEncode -p -e '$_ = encode("Shift JIS", decode("UTF-8", $_));' utf8_file.txt > sjis_file.txt
* 入力例 (utf8_file.txt):
これはUTF-8のテストです。
日本語

* 出力例 (sjis_file.txt): (Shift-JISとしてエンコードされた内容)
これはShift JISのテストです。
日本語

* 解説:
* -MEncode: Perlの組み込みモジュールであるEncodeを読み込みます。これにより、encodedecodeといった関数が使えるようになります。
* -p: 入力行を読み込み、処理後に自動出力します。
* -e '$_ = encode("Shift JIS", decode("UTF-8", $_));': 各行に対して実行されるコードです。
* decode("UTF-8", $_): 現在の行$_をUTF-8としてデコードし、Perl内部のワイドキャラクタ文字列(エンコーディングに依存しない表現)に変換します。
* encode("Shift JIS", ...): デコードされた内部表現の文字列を、Shift-JISとしてエンコードし、バイト列に戻します。
* $_ = ...: エンコードされた結果を$_に代入し直します。
* > sjis_file.txt: 標準出力をsjis_file.txtにリダイレクトします。

カテゴリ3:数値計算と集計 (Calculation & Aggregation)

ファイル内の数値データに対して計算を行ったり、合計や平均を求めたりするワンライナーです。BEGINブロックやENDブロックが役立つことがあります。

サンプル21:数値の列(フィールド)を合計する(空白区切り)

bash
$ perl -a -n -e '$sum += $F[0];' -e 'END { print $sum; }' data.txt

* 目的: 空白区切りのデータファイルの1列目にある数値を全て合計します。awk '{s+=$1} END {print s}' data.txtに似ています。
* コマンド: perl -a -n -e '$sum += $F[0];' -e 'END { print $sum; }' data.txt
* 入力例 (data.txt):
10 apple
25 banana
15 cherry

* 出力例:
50
* 解説:
* -a: 入力行を@Fに分割します。
* -n: 各行を処理するループを生成します。自動出力はしません。
* -e '$sum += $F[0];': 最初の-eブロックです。各行に対して実行されます。
* $sum: 数値を合計するためのスカラー変数です。Perlでは初めて使う変数にデフォルト値として数値コンテキストでは0、文字列コンテキストでは空文字列""が割り当てられるため、明示的な初期化なしで加算できます。
* +=: 加算代入演算子です。
* $F[0]: 現在の行の1列目の値です。これが$sumに加算されていきます。
* -e 'END { print $sum; }': 2番目の-eブロックです。
* END { print $sum; }: 全ての行の処理が終わった後に、最終的な合計値である$sumを出力します。

サンプル22:各行の数値に10を加える

bash
$ perl -p -e '$_ += 10;' numbers.txt

* 目的: 各行が数値であるファイルで、その数値に10を加えた結果を表示します。
* コマンド: perl -p -e '$_ += 10;' numbers.txt
* 入力例 (numbers.txt):
10
25
-5

* 出力例:
20
35
5

* 解説:
* -p: 各行を読み込み、処理後に自動出力します。
* $_ += 10;: 現在の行$_の内容を数値として扱い、それに10を加えて再び$_に代入します。Perlは文字列が数値として使える場合は自動的に数値として扱います。

サンプル23:特定の条件を満たす行の値を合計する

bash
$ perl -a -n -e 'next unless $F[1] =~ /pattern/;' -e '$sum += $F[0];' -e 'END { print $sum; }' data.txt

* 目的: 空白区切りのデータで、2列目(インデックス1)に特定のパターンを含む行の、1列目(インデックス0)の数値を合計します。
* コマンド: perl -a -n -e 'next unless $F[1] =~ /pattern/;' -e '$sum += $F[0];' -e 'END { print $sum; }' data.txt
* 入力例 (data.txt pattern=”a”):
10 apple
25 banana
15 cherry
5 mango

* 出力例:
40
* 解説:
* -a, -n: 各行を@Fに分割し、ループ処理します。
* -e 'next unless $F[1] =~ /pattern/;': 最初の-eブロックです。
* $F[1] =~ /pattern/: 2番目のフィールドが正規表現パターンにマッチするかテストします。
* next unless ...;: 条件が偽(2番目のフィールドがパターンにマッチしない)の場合、nextステートメントが実行されます。nextは現在のループの残りの処理をスキップし、次の繰り返し(次の行の読み込みと処理)に進みます。これにより、パターンにマッチしない行は後続の加算処理から除外されます。
* -e '$sum += $F[0];': 2番目の-eブロックです。前のブロックでnextされなかった行(つまりパターンにマッチした行)のみ、1番目のフィールド$F[0]$sumに加算します。
* -e 'END { print $sum; }': 3番目の-eブロックです。処理終了後に合計を出力します。

サンプル24:各行の数値の平均を計算する

bash
$ perl -n -e '$sum += $_; $count++;' -e 'END { print $sum / $count; }' numbers.txt

* 目的: 各行が数値であるファイルの、数値の平均を計算します。
* コマンド: perl -n -e '$sum += $_; $count++;' -e 'END { print $sum / $count; }' numbers.txt
* 入力例 (numbers.txt):
10
20
30

* 出力例:
20
* 解説:
* -n: 各行を$_に読み込み、ループ処理します。自動出力はしません。
* -e '$sum += $_; $count++;': 最初の-eブロックです。各行に対して実行されます。
* $sum += $_;: 現在の行の数値($_)を$sumに加算します。$sumは初回使用時に0に初期化されます。
* $count++;: 行数をカウントする変数$countをインクリメントします。$countも初回使用時に0に初期化されます。
* -e 'END { print $sum / $count; }': 2番目の-eブロックです。全ての行の処理が終わった後、合計$sumをカウント$countで割って平均値を計算し、出力します。

カテゴリ4:ファイルの操作 (File Manipulation)

入力ファイルを直接編集したり、複数のファイルを扱ったりするワンライナーです。-iオプションが中心になります。

サンプル25:ファイル内で「foo」を「bar」にインプレース置換する

bash
$ perl -i.bak -p -e 's/foo/bar/g;' file.txt

* 目的: file.txtファイルの内容を直接編集し、全ての「foo」を「bar」に置換します。元のファイルはfile.txt.bakとして保存されます。sed -i.bak 's/foo/bar/g' file.txtと同じ処理です。
* コマンド: perl -i.bak -p -e 's/foo/bar/g;' file.txt
* 入力例 (file.txt):
foo bar baz foo
another line with foo
no match here

* 処理後:
* file.txt:
bar bar baz bar
another line with bar
no match here

* file.txt.bak: (元の内容)
foo bar baz foo
another line with foo
no match here

* 解説:
* -i.bak: インプレース編集を指定します。元のファイルは.bak拡張子を付けてバックアップされます。Perlは一時ファイルを作成してそこに処理結果を書き出し、処理終了後に元のファイルを削除して一時ファイルをリネームするという手順でインプレース編集を行います。
* -p: 各行を処理し、結果を自動出力します。-iオプションがある場合、この出力は標準出力ではなく、-iが管理する一時ファイルに向けられます。
* s/foo/bar/g;: 各行に対して「foo」を「bar」にグローバル置換します。

サンプル26:ファイル内でパターンを含む行を削除する(インプレース)

bash
$ perl -i -n -e 'print unless /pattern/;' file.txt

* 目的: file.txtファイルの内容を直接編集し、特定のパターンを含む行を削除します。バックアップは作成しません。sed -i '/pattern/d' file.txtに似ています。
* コマンド: perl -i -n -e 'print unless /pattern/;' file.txt
* 入力例 (file.txt):
Line 1
Line 2 (contains pattern)
Line 3
Line 4 (also contains pattern)

* 処理後 (pattern=”contains”):
* file.txt:
Line 1
Line 3

* 解説:
* -i: インプレース編集を指定します。バックアップは作成されません。
* -n: 各行を読み込み、-eのコードを実行しますが、自動出力はしません。-iオプションがある場合、printは一時ファイルに出力されます。
* print unless /pattern/;: パターンを含まない行のみprintが実行され、一時ファイルに書き出されます。パターンを含む行はprintされないため、結果的にファイルから削除されます。

サンプル27:複数ファイルの処理

bash
$ perl -p -e 's/old/new/g;' file1.txt file2.txt file3.txt

* 目的: 複数のファイルに対して同じワンライナー処理(ここでは置換)を実行します。Perlワンライナーはコマンドライン引数で渡されたファイルを順番に処理します。
* コマンド: perl -p -e 's/old/new/g;' file1.txt file2.txt file3.txt
* 解説:
* file1.txt file2.txt file3.txt: 処理対象のファイルリストを指定します。Perlの< >演算子(-n-pで暗黙的に使用される)は、引数リストをファイル名として扱い、順番に開いて読み込みます。
* -p -e 's/old/new/g;': 各ファイルに対して、この置換処理が行われます。結果は標準出力に連続して出力されます。インプレース編集したい場合は-iオプションを追加します。

カテゴリ5:その他の便利なテクニック (Other Useful Techniques)

これまで紹介した基本以外にも、知っておくと便利なPerlワンライナーのテクニックを紹介します。

サンプル28:特定の文字セットのみを含む行を表示する

bash
$ perl -n -e 'print if /^[a-zA-Z0-9]+$/;' file.txt

* 目的: アルファベット(大文字・小文字)と数字のみで構成される行を表示します。パスワードリストの検証などに使えます。
* コマンド: perl -n -e 'print if /^[a-zA-Z0-9]+$/;' file.txt
* 入力例 (file.txt):
abc123
line with space
ONLYUPPER
mixedcase
12345
with-hyphen

* 出力例:
abc123
ONLYUPPER
mixedcase
12345

* 解説:
* -n: 各行を$_に読み込みます。
* if /^[a-zA-Z0-9]+$/;:
* ^: 行の先頭。
* [a-zA-Z0-9]: 文字クラスです。aからz、AからZ、0から9のいずれかの文字にマッチします。
* +: 直前の文字クラスが1回以上繰り返される場合にマッチします。
* $: 行の末尾。
* ^[a-zA-Z0-9]+$: 行全体が、アルファベットまたは数字の1つ以上の連続で構成されている場合にのみマッチします。
* パターンにマッチした行だけprintします。

サンプル29:各行の文字コードポイントを表示する

bash
$ perl -n -Mutf8 -e 'for my $char (split //, $_) { printf "%04X ", ord($char) } print "\n";' file.txt

* 目的: 各行の文字を一つずつ取り出し、その文字のUnicodeコードポイント(16進数)を表示します。マルチバイト文字の確認などに役立ちます。
* コマンド: perl -n -Mutf8 -e 'for my $char (split //, $_) { printf "%04X ", ord($char) } print "\n";' file.txt
* 入力例 (file.txt):
ABC あいう
123

* 出力例:
0041 0042 0043 0020 3042 3044 3046
0031 0032 0033

* 解説:
* -n: 各行を$_に読み込みます。
* -Mutf8: utf8プラグマを有効にします。これにより、ソースコードや文字列リテラルがUTF-8であると解釈され、マルチバイト文字が正しく扱われます。特に日本語などを扱う場合に重要です。
* -e '...': 各行に対して実行されるコードブロックです。
* split //, $_: split関数は文字列を分割します。区切り文字を空文字列''にすると、文字列を1文字ずつ分割し、その文字のリストを返します。
* for my $char (...): 分割された各文字をループで処理します。現在の文字は変数$charに格納されます。
* ord($char): Perlの組み込み関数ordは、引数で渡された文字の文字コードポイント(Unicodeの場合)を返します。
* printf "%04X ", ...: printf関数は、指定されたフォーマット文字列に従って出力します。%04Xは、数値を4桁の16進数(大文字)としてゼロ埋めして表示するフォーマット指定子です。各文字のコードポイントの後にスペースを付けて表示します。
* print "\n";: 内側のループ(文字ごとの処理)が終わった後、改行を出力します。-nオプションは行の自動出力を行いませんが、ここでは行を分解して文字ごとに出力しているため、手動で改行が必要です。

サンプル30:URLエンコード/デコード(一部)

bash
$ perl -MURI::Escape -p -e '$_ = uri_escape($_);' file.txt # エンコード
$ perl -MURI::Escape -p -e '$_ = uri_unescape($_);' file.txt # デコード

* 目的: 各行の内容をURLエンコードまたはデコードします。URI::Escapeモジュールを使用します。
* コマンド: 上記参照
* 入力例 (file.txt – エンコード):
スペースを含むファイル名.txt
日本語ファイル.csv

* 出力例 (エンコード):
%E3%82%B9%E3%83%9A%E3%83%BC%E3%82%B9%E3%82%92%E5%90%AB%E3%82%80%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E5%90%8D.txt
%E6%97%A5%E6%9C%AC%E8%AA%9E%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB.csv

* 入力例 (file.txt – デコード):
%E3%82%B9%E3%83%9A%E3%83%BC%E3%82%B9%E3%82%92%E5%90%AB%E3%82%80%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E5%90%8D.txt
%E6%97%A5%E6%9C%AC%E8%AA%9E%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB.csv

* 出力例 (デコード):
スペースを含むファイル名.txt
日本語ファイル.csv

* 解説:
* -MURI::Escape: URI::Escapeモジュールを読み込みます。これによりuri_escapeuri_unescape関数が使えるようになります。
* -p: 各行を読み込み、処理後に自動出力します。
* $_ = uri_escape($_);: 現在の行$_uri_escape関数でURLエンコードし、結果を$_に代入します。
* $_ = uri_unescape($_);: 現在の行$_uri_unescape関数でURLデコードし、結果を$_に代入します。
* これらの関数は、通常Web開発やデータ処理でURLに含める必要がある文字列を適切に処理する際に使用されます。

4章:ワンライナーを書く上でのヒントと注意点

  • 引用符の使い分け: コマンドラインシェルの特殊文字(例: $, !, ")の影響を避けるために、Perlコードはシングルクォート(')で囲むのが一般的です。コード内でシングルクォートを使いたい場合は、バックスラッシュでエスケープするか、ダブルクォート(")を使用することを検討してください(ただし、ダブルクォート内ではシェル変数も展開されてしまう可能性があるため注意が必要です)。
  • -lオプションの活用: 特に-nと組み合わせて、printするたびに自動的に改行を追加したい場合に非常に便利です。-pと組み合わせる場合も、入力行の改行をchompしてくれる効果があります。
  • -a-Fの組み合わせ: フィールド単位の処理を行う際に、awkのように手軽に扱えます。区切り文字を自由に指定できるのが強みです。
  • -iオプションは慎重に: ファイルを直接上書きするため、重要なファイルで試す際は必ずバックアップ(-i.bakのように拡張子を指定)を取るか、コピーに対して実行しましょう。
  • 標準入力とパイプ: ワンライナーはファイル名なしで実行すると標準入力からデータを読み込みます。これはパイプ(|)と組み合わせて、他のコマンドの出力をPerlワンライナーに渡す場合に非常に便利です。
    例:cat file.txt | perl -p -e 's/foo/bar/g;'
  • デバッグ: ワンライナーが期待通りに動かない場合は、
    • -cオプションを付けて構文チェックを行う:perl -c -e '...'
    • -MO=Deparseオプションを付けてPerlがコードをどう解釈しているか確認する(少し高度):perl -MO=Deparse -e '...' file.txt
    • printwarnを使って変数の内容や処理の途中経過を出力してみる。
    • 複雑な処理は無理にワンライナーにせず、通常のPerlスクリプトとして書く方が良い場合が多いです。ワンライナーはあくまで短く簡単なタスク向きです。

5章:まとめ

この記事では、Perlワンライナーの基本的な概念、主要なコマンドラインオプション、そして実践的な30のサンプルコードを詳細に解説しました。

Perlワンライナーは、その強力な正規表現能力とPerl言語の柔軟性を活かして、様々なテキスト処理タスクをコマンドラインから素早く実行できる非常に便利なツールです。grepsedawkといった既存のツールを補完したり、より複雑な処理を記述したりするのに役立ちます。

今回紹介したサンプルは、ワンライナーでできることのほんの一部に過ぎません。しかし、これらのサンプルを理解し、手を動かして試してみることで、Perlワンライナーの世界への第一歩を踏み出せるはずです。

ぜひ、日々の作業の中で「これはPerlワンライナーでできるかな?」と考えてみてください。少しずつ練習を重ねることで、きっとあなたのコマンドライン作業がより効率的になることを実感できるでしょう。

Happy Perling!


コメントする

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

上部へスクロール