テキスト ファイルの並べ替えに役立つ Awk コマンドラインまたはスクリプト (推奨)

テキスト ファイルの並べ替えに役立つ Awk コマンドラインまたはスクリプト (推奨)

Awk は、ソートを含む他の一般的なユーティリティによって実行できるいくつかのタスクを実行できる強力なツールです。

Awk は、予測可能なパターンを含むテキストをスキャンして処理するための、広く使用されている Unix コマンドです。しかし、機能的な能力を備えているため、プログラミング言語と呼ぶこともできます。

紛らわしいことに、awk は複数存在します。 (または、1 つしかないと思う場合、他はクローンです。) awk (Aho、Weinberger、および Kernighan によって書かれた元のプログラム) があり、次に nawk、mawk、および gawk の GNU バージョンがあります。 GNU バージョンの awk は、いくつかの独自の機能を備えたユーティリティの移植性の高いフリー ソフトウェア バージョンであるため、この記事では GNU awk について説明します。

正式名称は gawk ですが、GNU+Linux システムでは awk という別名が付けられ、コマンドのデフォルト バージョンとして使用されます。 GNU awk が付属していない他のシステムでは、まずそれをインストールし、awk ではなく gawk と呼ぶ必要があります。この記事では、awk と gawk という用語を同じ意味で使用します。

awk はコマンド言語であると同時にプログラミング言語でもあり、sort、cut、uniq などの一般的なユーティリティに使用されるタスクを実行するための強力なツールです。幸いなことに、オープンソースには冗長性の余地が十分にあるので、awk を使用するかどうかという質問に直面した場合、答えはおそらく「何でもいい」となるでしょう。

awk の柔軟性の優れた点は、タスクを実行するために awk を使用することを決定した場合、次に何が起こっても awk を使い続けることができることです。これには、データが配信された順序ではなく、データを並べ替えるという永続的な必要性が含まれます。

サンプルデータセット

awk のソート方法を調べる前に、作業に使用するサンプル データ セットを生成します。エッジケースや予期しない複雑さに悩まされないように、シンプルさを保ちます。この記事で使用したサンプル セットは次のとおりです。

アプテノディテス;フォルステリ;ミラー、JF;1778;皇帝
Pygoscelis;パプア;ワグラー;1832;ジェンツー
ユーディプトゥラ;マイナー;ボナパルト;1867;リトルブルー
Spheniscus;demersus;Brisson;1760;アフリカ
メガディプテス;対蹠類;ミルン・エドワーズ;1880;キバタヒバリ
Eudyptes;chrysocome;Viellot;1816;ミナミイワトビ
トルバルディス;Linux;ユーイング、L;1996;タックス

これは小さなデータセットですが、さまざまなデータ タイプを提供します。

  • 属名と種名は関連しているが別々である
  • 姓、イニシャルの場合は先頭にコンマを付ける
  • 日付を表す整数
  • 任意の用語
  • すべてのフィールドはセミコロンで区切られます。

教育的背景に応じて、これを 2 次元配列またはテーブル、あるいは単に行で区切られたデータのコレクションと考えることができます。どのように見るかはあなたの問題です。awk はテキストのみを認識します。どのように解析するかを awk に指示するのはあなた次第です。

並べ替えたいだけ

テキスト データセットを特定の定義可能なフィールド (スプレッドシートの「セル」など) でのみ並べ替える場合は、sort コマンドを使用できます。

フィールドとレコード

入力の形式に関係なく、重要なデータ部分に焦点を当てることができるように、入力内のパターンを見つける必要があります。この例では、データは行とフィールドという 2 つの要素によって区切られています。各行は、スプレッドシートやデータベース ダンプに表示されるのと同じように、新しいレコードを表します。各行には、セミコロン (;) で区切られたさまざまなフィールド (スプレッドシートのセルのようなものと考えてください) があります。

Awk は一度に 1 つのレコードのみを処理するため、awk に送信される命令を作成するときは、レコードの 1 行のみに集中できます。 1 行のデータで何をしたいかを書き留め、次の行でそれをテストし (頭の中で、または awk を使用して)、その後、他のテストをいくつか実行します。最後に、awk スクリプトが処理するデータについていくつかの仮定を立てて、必要な構造でデータを提供できるようにする必要があります。

この例では、各フィールドがセミコロンで区切られていることが簡単にわかります。簡単にするために、各行の最初のフィールドでリストを並べ替えるとします。

ソートを実行する前に、awk が各行の最初のフィールドのみにフォーカスするようにする必要があります。これが最初のステップです。ターミナルでの awk コマンドの構文は、awk、その後に関連するオプション、最後に処理するデータ ファイルです。

$ awk --field-separator=";" '{print $1;}' ペンギンリスト
アプテノダイテス
ピゴセリス
ユーディプトゥラ
スフェニスカス
メガディプテス
ユーディプテス
トルバルディス

フィールド区切り文字は Bash シェルにとって特別な意味を持つ文字であるため、セミコロンを引用符で囲むか、その前にバックスラッシュを付ける必要があります。このコマンドは、特定の分野に特化できることを証明するためにのみ使用されます。別のフィールド番号を使用して同じコマンドを実行し、データの別の「列」の内容を確認することもできます。

$ awk --field-separator=";" '{print $3;}' ペンギンリスト
ミラー、J.F.
ワグラー
ボナパルト
ブリッソン
ミルン・エドワーズ
ヴィエロ
ユーイング、L

まだソートは行っていませんが、これは良い基礎です。

スクリプト

awk は単なるコマンドではなく、インデックス、配列、関数を備えたプログラミング言語です。これは、並べ替えるフィールドのリストを取得し、そのリストをメモリに保存し、処理を実行して、結果のデータを印刷できることを意味するため重要です。このような複雑な一連の操作の場合は、テキスト ファイルで実行する方が簡単なので、sort.awk という新しいファイルを作成し、次のテキストを入力します。

#!/bin/gawk -f
始める {
    FS=";";
}

これにより、実行される行を含む awk スクリプトにファイルが構築されます。

BEGIN ステートメントは、1 回だけ実行する必要があるタスク用に awk によって提供される特別なセットアップ関数です。組み込み変数 FS を定義します。これはフィールド区切り文字を表し、awk コマンドの --field-separator で設定する値と同じです。これは 1 回だけ実行する必要があるため、BEGIN ステートメントに含まれています。

awk の配列

$ 記号とフィールド番号を使用して特定のフィールドの値を収集する方法はすでにご存知ですが、この場合は、ターミナルに出力するのではなく、配列に保存します。これは awk 配列を使用して行われます。 awk 配列に関して重要なことは、キーと値が含まれていることです。 この記事の内容を想像してみてください。次のようになります: author:"seth",title:"How to sort with awk",length:1200。著者、タイトル、長さなどの要素がキーであり、それに続くコンテンツが値です。

ソートのコンテキストでこれを行う利点は、任意のフィールドをキーとして割り当て、任意のレコードを値として割り当て、組み込みの awk 関数 asorti() (インデックスによるソート) を使用してキーでソートできることです。ここで、2 番目のフィールドのみで並べ替えたいと仮定してみましょう。

特殊キーワード BEGIN または END で囲まれていない awk ステートメントは、各レコードに対して実行されるループです。これは、データをスキャンしてパターンを検出し、それに応じて処理するスクリプトの部分です。 awk がレコードに注目するたびに、{} 内のステートメントが実行されます (BEGIN または END が先行しない限り)。

配列にキーと値を追加するには、配列を含む変数を作成し (このサンプル スクリプトでは ARRAY と呼びます。あまり独創的ではありませんがわかりやすいです)、角括弧で囲んだキーと等号 (=) で囲んだ値を割り当てます。

{ # 各フィールドを配列にダンプする
  配列[$2] = $R;
}

このステートメントでは、2 番目のフィールド ($2) の内容がキーとして使用され、現在のレコード ($R) が値として使用されます。

asorti() 関数

配列に加えて、awk には、一般的なタスクの迅速かつ簡単なソリューションとして使用できるいくつかの基本関数があります。 GNU awk で導入された関数の 1 つである asorti() は、配列をキー (インデックス) または値でソートする機能を提供します。

配列を並べ替えることができるのは、配列にデータが入力された後のみです。つまり、この操作は新しいレコードごとにトリガーされるのではなく、スクリプトの最後でのみトリガーされます。この目的のために、awk は特別な END キーワードを提供します。 BEGIN とは異なり、END ステートメントはすべてのレコードがスキャンされた後に 1 回だけ実行されます。

スクリプトに以下を追加します:

終わり {
  配列をソートする
  # 長さを取得
  j = 長さ(SARRAY);
  
  (i = 1; i <= j; i++) の場合 {
    printf("%s %s\n", SARRAY[i],ARRAY[SARRAY[i]])
  }
}

asorti() 関数は ARRAY の内容を受け取り、インデックスでソートし、その結果を SARRAY (この記事のために私が作った任意の名前で、「sorted ARRAY」の略) という新しい配列に格納します。

次に、変数 j (別の任意の名前) に、SARRAY 内の項目数をカウントする length() 関数の結果が割り当てられます。

最後に、 for ループを使用して、printf() 関数を使用して SARRAY 内の各項目を反復処理し、各キーを出力してから、ARRAY 内のそのキーに対応する値を出力します。

スクリプトを実行する

awk スクリプトを実行するには、実行可能にします。

$ chmod +x sorter.awk

次に、penguin.list のサンプル データに対して実行します。

$ ./sorter.awk ペンギンリスト
対蹠類メガディプテス;対蹠類;ミルン・エドワーズ;1880;キバタヒバリ
クリソコム Eudyptes;クリソコム;Viellot;1816;サザンイワトビ
demersus Spheniscus;demersus;Brisson;1760;アフリカ
forsteri Aptenodytes;forsteri;Miller,JF;1778;Emperor
linux Torvaldis;linux;Ewing,L;1996;Tux
マイナー Eudyptula;マイナー;ボナパルト;1867;リトルブルー
パプア Pygoscelis;パプア;ワグラー;1832;ジェンツー

ご覧のとおり、データは 2 番目のフィールドでソートされています。

これは少し制限があります。このスクリプトを任意のデータセットで使用して意味のある結果を得るためには、実行時にソートキーとして使用するフィールドを柔軟に選択できると便利です。

コマンドオプションを追加する

スクリプト内でリテラル値 var を使用して、awk スクリプトにコマンド変数を追加できます。配列を作成するときに反復句が var を使用するようにスクリプトを変更します。

{ # 各フィールドを配列にダンプする
  配列[$var] = $R;
}

スクリプトを実行するときに -v var オプションを使用して、3 番目のフィールドでソートされるようにスクリプトを実行してみてください。

$ ./sorter.awk -v var=3 ペンギンリスト
ボナパルト エウディプトゥラ;マイナー;ボナパルト;1867;リトルブルー
Brisson Spheniscus;demersus;Brisson;1760;アフリカ
Ewing、L Torvaldis;linux;Ewing、L;1996;Tux
ミラー、JF アプテノディテス;フォルステリ;ミラー、JF;1778;皇帝
ミルン-エドワーズ メガディプテス;対蹠類;ミルン-エドワーズ;1880;キバタヒバリ
Viellot Eudyptes;chrysocome;Viellot;1816;ミナミイワトビ
Wagler Pygoscelis;パプア;Wagler;1832;ジェンツー

リビジョン

この記事では、純粋な GNU awk でデータをソートする方法を説明します。スクリプトを自分にとって便利なものに改善するには、gawk のマニュアル ページで awk 関数を時間をかけて学習し、スクリプトをカスタマイズしてより良い出力を得ることができます。

これまでの完全なスクリプトは次のとおりです。

#!/usr/bin/awk -f
# GPLv3がここに登場
# 使用法: ./sorter.awk -v var=NUM FILE
開始 { FS=";"; }
{ # 各フィールドを配列にダンプする
  配列[$var] = $R;
}
終わり {
  配列をソートする
  # 長さを取得
  j = 長さ(SARRAY);
  
  (i = 1; i <= j; i++) の場合 {
    printf("%s %s\n", SARRAY[i],ARRAY[SARRAY[i]])
  }
}

要約する

上記は、テキスト ファイルの並べ替えに役立つ Awk コマンドラインまたはスクリプトです。お役に立てば幸いです。ご質問がある場合は、メッセージを残してください。すぐに返信いたします。また、123WORDPRESS.COM ウェブサイトをサポートしてくださっている皆様にも感謝申し上げます。
この記事が役に立ったと思われた方は、ぜひ転載していただき、出典を明記してください。ありがとうございます!

以下もご興味があるかもしれません:
  • awk スクリプトを Python に移植する方法
  • シェルスクリプトの正規表現、grep、sed、awk
  • シェルスクリプトでのawkコマンドの使用
  • Linuxシェルスクリプトでは、配列がawkに渡されて処理されます。
  • Linux awk 時間計算スクリプトと awk コマンドの詳細な説明

<<:  MySQL に大量のデータを挿入する 4 つの方法の例

>>:  WeChatアプレットはシンプルな手書き署名コンポーネントを実装します

推薦する

MySQL 8.0.20 のインストールと設定方法のグラフィックチュートリアル

MySQLのダウンロードとインストール(バージョン8.0.20)のチュートリアルは参考までに、具体的...

MySql の集計関数に条件式を追加する方法

MySQL のフィルタリングのタイミングは、集計関数で使用される where 条件と having ...

CSS3 で Taobao に空白スペースを実装する方法

Taobao用の空白スペースを作成します。 ブラウザページを縮小すると、コンテンツ領域は縮小されませ...

開発効率の向上に役立つ 56 個の実用的な JavaScript ツール関数

目次1. デジタルオペレーション(1)指定された範囲内で乱数を生成する2. 配列操作(1)配列の順序...

MySQL インデックスの一般的な問題の概要

Q1: データベースにはどのようなインデックスがありますか?メリットとデメリットは何ですか? 1. ...

Web面接でよくある質問:リフローとリペイントの原理と違い

目次ブラウザのレンダリングメカニズムリフローと再塗装リフロー逆流を引き起こす行為:再描画再描画を引き...

Dockerボリューム権限管理の詳細な説明

ボリュームデータボリュームは Docker の重要な概念です。データ ボリュームは、1 つ以上のコン...

uniAppエディタWeChatスライド問題について

ユニアプリアプレットはWeChatでも同様のドロップダウン問題を抱えることになる解決策は、app.v...

MySQL 5.7 mysql コマンドラインクライアントの使用コマンドの詳細

MySQL 5.7コマンドを使用するMySQLコマンドラインクライアント1. パスワードを入力してく...

MySQL データを誤って削除した場合の簡単な解決策 (MySQL フラッシュバック ツール)

概要Binlog2sql は、Python で開発されたオープンソースの MySQL Binlog ...

MySQL Undo ログと Redo ログの概要

目次元に戻すログUNDOログの生成と破棄UNDOログの保存元に戻すログ機能トランザクションの原子性の...

Tomcat の静的ページ (html) で中国語の文字化けが発生する問題の究極の解決策

tomcatでは、jspは文字化けしませんが、htmlの中国語は文字化けします理由はいくつかあります...

Vue フロントエンドの Excel ファイルのエクスポートの詳細な実装計画

目次1. 技術の選択2. 技術的な実装vue-json-excelプラグインを使用して実装1. vu...

JavaScript の高度なプログラミングの基本参照型

目次1. 日付2. 正規表現3. オリジナルパッケージタイプ序文:参照値(オブジェクト)は、 Dat...

HTML+CSS をベースにした素敵なフリップログインおよび登録インターフェースを作成します

素敵なフリップログインと登録インターフェースを作成する序文最近、ネットワーク ディスクを構築しようと...