テキスト ファイルの並べ替えに役立つ 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 での大規模トランザクションによって発生する挿入の遅延ケースの分析

【質問】 INSERT 文は最も一般的な SQL 文の 1 つです。最近、MySQL サーバーが同時...

Vueはダイアログのカプセル化を実装します

目次Vue2 ライティングVue3プラグインのバージョンの記述Vue3 動的コンポーネントの記述書き...

HTML に埋め込まれた Flash HTML ウェブページ コードに Flash ファイルを埋め込むソリューション (パート 1)

中国の習慣では、旧暦の1月15日より前に新年を祝います。ここで、庭にいる友人たちに新年の幸せを祈りた...

Zabbix による VMware Exsi ホストの監視のグラフィカルな手順

1. 仮想化 vcenter に入り、ブラウザでログインし (クライアントは設定する場所を見つけませ...

MySQL のスローログオンラインの問題と最適化ソリューション

MySQL スロー ログは、MySQL DBA やその他の開発および運用担当者が細心の注意を払う必要...

npmとcnpmを混在させる際の落とし穴の詳細な説明

目次原因理由NPM の紹介: CNPM の紹介:より良い方法方法の改善npm と cnpm を一緒に...

Linuxでpyファイルを直接実行する方法

1. まずファイルを作成します(ファイルを配置するディレクトリにcdします) myTest.py を...

MySQL が起動直後にシャットダウンする問題 (ibdata1 ファイルの破損が原因) に対する完璧な解決策

コンピュータ ルームのサーバー上の mysql がしばらく実行されていたのですが、突然、再起動しても...

PrometheusはGrafanaディスプレイを使用してMySQLを監視します

目次Prometheusはエクスポーターを介してMySQLを監視し、Grafanaチャートで表示しま...

int(3)とint(10)の値の範囲はmysqlで同じですか?

目次質問:答え:現実:知識ポイント結論は:要約する質問: MySQLフィールド、unsigned i...

Linux に nodejs 環境とパス構成をインストールするための詳細な手順

Linux に Node.js をインストールする方法は 2 つあります。1 つは簡単で、解凍して使...

Docker コンテナのカスタム ホストのネットワーク アクセス操作

docker-compose.yml に extra_hosts キーワードを追加すると、コンテナの...

Ajax の JavaScript ソリューションにおける parsererror エラー ケースの詳細な説明

ajax の parsererror エラー (バックグラウンドからフロントエンドに送信される js...

MySqlは、外部ネットワーク接続クライアントの低速問題を解決するためにskip-name-resolveを使用します。

Tencent Cloud上に構築されたMySQLは、開発用コンピュータでNavicatを使用して...

JavaScript オブジェクト指向クラス継承ケースの説明

1. オブジェクト指向のクラス継承これまでの章では、JavaScript のオブジェクト モデルがプ...