Linuxでawkを使用する方法の詳細な説明

Linuxでawkを使用する方法の詳細な説明

awk を学ぶ前に、sed、grep、tr、cut などのコマンドを学んでおく必要があります。これらのコマンドはすべて Linux でのテキストおよびデータ処理に便利ですが、多くの場合、これらのコマンドでは一度にニーズを完全に満たすことはできません。多くの場合、これらのコマンドと組み合わせてパイプ記号を使用する必要があります。今日は、テキストおよびデータ処理のニーズを十分に満たし、1 つのコマンドで多くの問題を解決できる awk コマンドを紹介します。

1. awkコマンドの紹介

Awk はテキスト処理の三銃士の 1 つとして知られています。その名前は、創設者である Alfred Aho、Peter Weinberger、Brian Kernighan の姓の頭文字に由来しています。実際、AWK には独自の言語、AWK プログラミング言語があり、3 人の作成者はこれを「パターン スキャンおよび処理言語」として正式に定義しています。入力ファイルの読み取り、データの並べ替え、データの処理、入力の計算、レポートの生成など、さまざまな機能を実行する短いプログラムを作成できます。
したがって、awk は強力なテキスト分析ツールです。grep の検索や sed の編集と比較すると、awk はデータの分析やレポートの生成に関しては特に強力です。簡単に言うと、awk はファイルを 1 行ずつ読み取り、デフォルトの区切り文字としてスペースを使用して各行をスライスし、スライスされた部分に対してさまざまな分析と処理を実行します。

2. awkコマンドの形式とオプション

文法形式

awk [オプション] 'script' var=値 ファイル
awk [オプション] -f スクリプトファイル var=値 ファイル

共通コマンドオプション

-F fs fs は入力セパレーターを指定します。fs は文字列または正規表現 (-F な​​ど) にすることができます。
-v var=value ユーザー定義変数を割り当て、外部変数をawkに渡す
-f scripfile スクリプトファイルからawkコマンドを読み込む
-m[fr] val は、val の値に内部制限を設定します。-mf オプションは、val に割り当てられるブロックの最大数を制限し、-mr オプションはレコードの最大数を制限します。これら 2 つの関数は Bell Lab バージョンの awk の拡張機能であり、標準の awk には適用できません。

3. awkの原理

awk 'BEGIN{ commands } pattern{ commands } END{ commands }'

ステップ 1: BEGIN{commands} ステートメント ブロック内のステートメントを実行します。
ステップ 2: ファイルまたは標準入力 (stdin) から 1 行を読み取り、pattern{commands} ステートメント ブロックを実行します。このステートメント ブロックは、ファイルを 1 行ずつスキャンし、ファイル全体が読み取られるまで、最初の行から最後の行までこのプロセスを繰り返します。
ステップ 3: 入力ストリームの最後まで読み取るときに、END{commands} ステートメント ブロックを実行します。
BEGIN ステートメント ブロックは、awk が入力ストリームから行の読み取りを開始する前に実行されます。これはオプションのステートメント ブロックです。変数の初期化や出力テーブル ヘッダーの印刷などのステートメントは、通常、BEGIN ステートメント ブロックに記述できます。

END ブロックは、awk が入力ストリームからすべての行を読み込んだ後に実行されます。たとえば、すべての行の解析結果を出力するなどの情報の要約は、END ブロックで完了します。これもオプションのブロックです。

パターン ブロック内の共通コマンドは最も重要な部分ですが、オプションでもあります。パターン ステートメント ブロックが指定されていない場合は、デフォルトで { print } が実行されます。つまり、読み取られた各行が印刷され、awk によって読み取られた各行に対してステートメント ブロックが実行されます。

4. awkの基本的な使い方

awkを呼び出す方法は3つあります

1. コマンドライン方式

awk [-F field-separator] 'commands' input-file(s)

これらのうち、コマンドは実際のawkコマンドであり、[-F フィールドセパレーター]はオプションです。 input-file(s) は処理されるファイルです。
awk では、ファイルの各行でフィールド区切り文字によって区切られた各項目をフィールドと呼びます。通常、-F でフィールド区切り文字を指定しない場合、デフォルトのフィールド区切り文字はスペースになります。

2. シェルスクリプト方式

awk 'BEGIN{ print "start" } pattern{ commands } END{ print "end" }' file

awk スクリプトは通常、BEGIN ステートメント ブロック、パターン マッチングを使用できる一般的なステートメント ブロック、および END ステートメント ブロックの 3 つの部分で構成されます。これらの 3 つの部分はオプションです。どちらの部分もスクリプト内に現れる必要はなく、通常は一重引用符または二重引用符で囲まれます。次に例を示します。

awk 'BEGIN{ i=0 } { i++ } END{ print i }' ファイル名
awk "BEGIN{ i=0 } { i++ } END{ print i }" ファイル名

3. すべてのawkコマンドを別のファイルに挿入し、

awk -f awkスクリプトファイル 入力ファイル

-f オプションは awk-script-file 内の awk スクリプトをロードし、input-file(s) は上記のコマンドライン方式と同じです。
awkの使い方をさらに理解するために、いくつかの簡単な例を見てみましょう。

[root@localhost ~]# awk '{print $0}' /etc/passwd 
ルート:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/ログインなし
デーモン:x:2:2:デーモン:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
同期:x:5:0:sync:/sbin:/bin/sync
シャットダウン:x:6:0:シャットダウン:/sbin:/sbin/シャットダウン
停止:x:7:0:停止:/sbin:/sbin/停止
.............................................................................
[root@localhost ~]# echo 123|awk '{print "hello,awk"}'
こんにちは、awk

[root@localhost ~]# awk '{print "hi"}' /etc/passwd
こんにちは
こんにちは
こんにちは
こんにちは
こんにちは
こんにちは
こんにちは
こんにちは
こんにちは
.............................................................................


出力ファイルとして /etc/passwd を指定します。awk を実行すると、/etc/passwd 内の各行に対して print コマンドが順番に実行されます。

awk ワークフローは次のとおりです: '\n' 改行文字で区切られたレコードを読み取り、指定されたフィールド区切り文字に従ってレコードをフィールドに分割し、フィールドを埋めます。$0 はすべてのフィールドを表し、$1 は最初のフィールドを表し、$n は n 番目のフィールドを表します。デフォルトのドメイン区切り文字は「空白」または「[tab] キー」なので、$1 はログインしたユーザーを表し、$3 はログインしたユーザーの IP を表します。のように

/etc/passwd の下にあるすべてのユーザー名を印刷します。

[root@localhost ~]# awk -F: '{print $1}' /etc/passwd
根
ビン
デーモン
管理者

........................................................................
/etc/passwd の下にあるすべてのユーザー名と UID を印刷します。

[root@localhost ~]# awk -F: '{print $1,$3}' /etc/passwd
ルート0
ビン1
デーモン2

........................................................................
ユーザー名: XXX uid: XXX の形式で出力します

[root@localhost ~]# awk -F: '{print "ユーザー名: " $1 "\t\tuid: "$3}' /etc/passwd
ユーザー名: root uid: 0
ユーザー名: bin uid: 1
ユーザー名: デーモン UID: 2
........................................................................


5. awk組み込み変数

変数説明する
\$n 現在のレコードのn番目のフィールド(FSで区切られる)
\$0 入力レコードを完了する
ARGC コマンドライン引数の数
アルギンドコマンドラインにおける現在のファイルの位置(0から始まる)
ARGB コマンドライン引数を含む配列
変換FMT 数値変換形式(デフォルト値は%.6g) ENVIRON 環境変数連想配列
エラー最後のシステムエラーの説明
フィールド幅フィールド幅のリスト(スペースで区切る)
ファイル名現在のファイル名
金融ファイルごとに行番号を別々にカウントします
FS フィールド区切り文字(デフォルトは任意のスペース)
大文字と小文字を無視 true の場合、大文字と小文字を区別しない一致を実行します。
NF レコード内のフィールド数
NR 読み込まれたレコードの数、つまり1から始まる行番号
OFMT 数値の出力形式(デフォルトは%.6g)
オフス出力レコード区切り(出力改行)、出力時に改行を指定された記号に置き換えます
経口摂取出力レコードセパレータ(デフォルトは改行文字)
長さマッチ関数によってマッチした文字列の長さ
RS レコード区切り文字(デフォルトは改行文字)
RSTART マッチ関数によってマッチした文字列の最初の位置
サブセプ配列の添え字区切り文字(デフォルト値は /034)

[root@localhost ~]# echo -e "line1 f2 f3\nline2 f4 f5\nline3 f6 f7" | awk '{print "行番号:"NR", フィールド数:"NF, "$0="$0, "$1="$1, "$2="$2, "$3="$3}'
行番号:1、フィールド数:3 $0=line1 f2 f3 $1=line1 $2=f2 $3=f3
行番号:2、フィールド数:3 $0=line2 f4 f5 $1=line2 $2=f4 $3=f5
行番号:3、フィールド数:3 $0=line3 f6 f7 $1=line3 $2=f6 $3=f7

行の最後のフィールドを印刷するには print $NF を使用し、最後から 2 番目のフィールドを印刷するには $(NF-1) を使用します。

[root@localhost ~]# echo -e "line1 f2 f3\n line2 f4 f5" | awk '{print $NF}'
f3
f5
[root@localhost ~]# echo -e "line1 f2 f3\n line2 f4 f5" | awk '{print $(NF-1)}'
2 番目
f4

/etc/passwd の統計: ファイル名、行番号、行あたりの列数、および対応する完全な行の内容:

[root@localhost ~]# awk -F ':' '{print "ファイル名:" FILENAME ",行番号:" NR ",列:" NF ",行内容:"$0}' /etc/passwd
ファイル名:/etc/passwd、行番号:1、列数:7、行内容:root:x:0:0:root:/root:/bin/bash
ファイル名:/etc/passwd、行番号:2、列数:7、行内容:bin:x:1:1:bin:/bin:/sbin/nologin
ファイル名:/etc/passwd、行番号:3、列数:7、行内容:デーモン:x:2:2:デーモン:/sbin:/sbin/nologin

/etc/passwd ファイル内のコマンドラインパラメータ ARGC (ファイルの行番号)、FNR (フィールド区切り文字)、FS (レコード内のフィールド数)、NF (読み取られたレコード数 (デフォルトは行番号))、NR をカウントします。

[root@localhost ~]# awk -F: 'BEGIN{printf "%4s %4s %4s %4s %4s %4s\n","FILENAME","ARGC","FNR","FS","NF","NR";printf "---------------------------------------------\n"} {printf "%4s %4s %4s %4s %4s\n",FILENAME,ARGC,FNR,FS,NF,NR}' /etc/passwd
ファイル名 ARGC FNR FS NF NR
---------------------------------------------
/etc/passwd 2 1 : 7 1
/etc/passwd 2 2 : 7 2
/etc/passwd 2 3 : 7 3


6. awkの高度な使い方

1.awk代入操作

代入文の演算子: = += -= *= /= %= ^= **=

例えば、a+=5はa=a+5と同等である。

[root@localhost ~]# awk 'BEGIN{a=5;a+=5;print a}'
10

2.awkの通常操作の出力にはルートの行が含まれており、ユーザー名とUID、元の行の内容が出力されます。

[root@localhost ~]# awk -F: '/root/ {print $1,$3,$0}' /etc/passwd
ルート 0 ルート:x:0:0:root:/root:/bin/bash
演算子 11 演算子:x:11:0:演算子:/root:/sbin/nologin

2行見つかりました。rootで始まる行を見つけたい場合は、次のように記述する必要があります: awk -F: '/^root/' /etc/passwd

3.awk三項演算

[root@localhost ~]# awk 'BEGIN{a="b";print a=="b"?"ok":"err"}'
わかりました
[root@localhost ~]# awk 'BEGIN{a="b";print a=="c"?"ok":"err"}'
間違い

三項演算は実際には判定演算です。真であれば出力は?偽の場合は、次のように出力します。

4. awkの循環使用

if文の使用

[root@localhost ~]# awk 'BEGIN{ test=100;if(test>90){ print "vear good";} else{print "no pass";}}'
着心地が良い

各コマンドは ; で終わります。
whileループは1から100までの値を計算する

[root@localhost ~]# awk 'BEGIN{test=100;num=0;while(i<=test){num+=i; i++;}print num;}'
5050
for ループの使用 [root@localhost ~]# awk 'BEGIN{test=0;for(i=0;i<=100;i++){test+=i;}print test;}'
5050
do ループの使用 [root@localhost ~]# awk 'BEGIN{test=0;i=0;do{test+=i;i++}while(i<=100)print test;}'
5050

5. awkの配列アプリケーション

配列は awk の魂です。テキスト処理で最も重要なことは配列処理です。配列のインデックス (添え字) には数値と文字列が使用できるため、awk の配列は連想配列と呼ばれます。 awk の配列は事前に宣言する必要はなく、サイズを指定する必要もありません。配列要素は、コンテキストに応じて 0 または空の文字列で初期化されます。一般的に、awk の配列はレコードから情報を収集するために使用され、合計を計算したり、単語を数えたり、テンプレートが一致した回数を追跡したりするために使用できます。
/etc/passwd内のアカウントを表示する

awk -F: 'BEGIN {count=0;} {name[count] = $1;count++;}; END{for (i = 0; i < NR; i++) print i, name[i]}' /etc/passwd
0 ルート
1ビン
2 デーモン
3 アドミン
4 lp
5 同期
........................................................................


6. awk文字列関数の応用

関数名の説明
sub は、レコードの最も大きい左端の部分文字列を正規表現に一致させ、それを置換文字列に置き換えます。ターゲット文字列が指定されていない場合は、デフォルトでレコード全体が使用されます。置換は最初の一致に対してのみ行われます。
sub (正規表現、置換文字列):
sub (正規表現、置換文字列、対象文字列)

例:

     awk '{ sub(/test/, "mytest"); print }' テストファイル
     awk '{ sub(/test/, "mytest"); $1}; print }' テストファイル

最初の例はレコード全体と一致し、一致が最初に出現した場合にのみ置換が行われます。ファイル全体を一致させたい場合にはgsubを使う必要があります

2 番目の例は、レコード全体の最初のフィールドと一致し、最初の一致に対してのみ置換が行われます。
gsubは文書全体にマッチする
gsub (正規表現、置換文字列)
gsub (正規表現、置換文字列、対象文字列)

例:

     awk '{ gsub(/test/, "mytest"); print }' テストファイル
     awk '{ gsub(/test/, "mytest" , $1) }; print }' テストファイル

最初の例では、ドキュメント全体で test に一致し、一致した部分はすべて mytest に置き換えられます。

2 番目の例は、ドキュメント全体の最初のフィールドと一致し、すべての一致が mytest に置き換えられます。
インデックスは、位置1から始まるオフセットで、部分文字列が最初に一致する位置を返します。
インデックス(文字列、部分文字列)

例:

awk '{ print index("test", "mytest") }' testfile

この例では、mytest 内の test の位置が返され、結果は 3 になります。
substr は位置 1 から始まる部分文字列を返します。指定された長さが実際の長さを超える場合は、文字列全体が返されます。
substr(文字列、開始位置)
substr( 文字列、開始位置、文字列の長さ )

例:

awk '{ print substr( "hello world", 7,11 ) }'

上記の例では、ワールド部分文字列を抽出します。
split は、指定された区切り文字に従って文字列を配列に分割できます。区切り文字が指定されていない場合、データは現在の FS 値に従って分割されます。
split(文字列、配列、フィールド区切り文字)
split(文字列、配列)

例:

awk '{ split( "20:18:00", time, ":" ); print time[2] }'

上記の例では、時間をコロンで分割して時間配列にし、2 番目の配列要素 18 を表示します。
長さ レコード内の文字数を返します
長さ(文字列)
長さ

例:

     awk '{ 長さを印刷( "テスト" ) }' 
     awk '{ 長さを印刷 }' テストファイル


最初の例では、テスト文字列の長さを返します。

2 番目の例では、testfile ファイル内のレコード内の文字数を返します。
match は文字列内の正規表現の位置のインデックスを返します。指定された正規表現が見つからない場合は 0 を返します。 match 関数は、組み込み変数 RSTART を文字列内の部分文字列の開始位置に設定し、RLENGTH を部分文字列の末尾までの文字数に設定します。 substrはこれらの変数を使用して文字列を傍受することができます

match(文字列、正規表現)

例:

     awk '{start=match("これはテストです",/[az]+$/); print start}'
     awk '{start=match("これはテストです",/[az]+$/); print start, RSTART, RLENGTH }'


最初の例では、連続する小文字で終わるシーケンスの開始位置 (この場合は 11) を出力します。

2 番目の例では、RSTART 変数と RLENGTH 変数も出力されます。これらは 11 (開始)、11 (RSTART)、4 (RLENGTH) です。
toupperとtolowerは文字列のサイズを変換するために使用できます。この関数はgawkでのみ有効です。

toupper(文字列)
tolower(文字列)

例:

awk '{ print toupper("test"), tolower("TEST") }'

以下もご興味があるかもしれません:
  • Linux の awk における split 関数の使用法の概要
  • Linux正規表現awkの詳しい説明
  • 1日1シェルコマンド Linuxテキストコンテンツ操作シリーズ - awkコマンド詳細説明
  • Linux での sed と awk の使い方の詳細な説明
  • Linux awk 時間計算スクリプトと awk コマンドの詳細な説明
  • 外部変数を取得する Linux シェル awk の紹介 (変数値の転送)
  • Linux での awk コマンドの使用
  • Linux awk の高度なアプリケーション例
  • ファイルの列をコンマで区切る Linux awk の例

<<:  vue-tableは追加と削除を実装します

>>:  MySQL 8.0.12 解凍バージョンのインストールチュートリアル

推薦する

Vueは指定された日付間のカウントダウンを実装します

この記事では、指定された日付間のカウントダウンを実装するためのVueの具体的なコードを例として紹介し...

Windows Server 2008 64ビット MySQL5.6 インストール不要版 設定方法図

1 公式ウェブサイトから MySQL 5.6 バージョンの圧縮パッケージmysql-5.6.36-w...

VMware で VMware ツールをインストールしてもインストール ファイルが表示されない問題を解決する方法

VMware ツールは VMware の使用に非常に便利です。そのため、VMware ツールをインス...

Linux で Squid プロキシ サーバーを構築するための完全な手順

序文この記事では、Linux で Squid プロキシ サーバーを設定することに関する関連コンテンツ...

Vueはvueメタ情報を使用して各ページのタイトルとメタ情報を設定します。

title: vue は vue-meta-info を使用して各ページのタイトルとメタ情報を設定...

CentOS 7 に Percona Server+MySQL をインストールする

1. 環境の説明(1) CentOS-7-x86_64、カーネルバージョン uname -r は、 ...

MySQL 整合性制約の定義と例のチュートリアル

目次整合性制約整合性制約の定義整合性制約の分類主キー制約単一の主キーと複合主キーの違い主キーフィール...

ウェブページ印刷細線表+ページ印刷究極の戦略

最近、クライアントのために印刷していたとき、ページのヘッダーを印刷するのではなく、表の内容だけを印刷...

mysql 3つのテーブルを接続してビューを作成する

3 つのテーブルが接続されています。テーブル A のフィールド a はテーブル B のフィールド b...

Nginx サーバーが Systemd カスタム サービス プロセス分析を追加

1. nginxを例に挙げるyumコマンドを使用してNginxをインストールしましたSystemd ...

Vue はコンポーネント間の通信をどのように実装しますか?

目次1. 父と息子のコミュニケーション1.1 親コンポーネント --> 子コンポーネント1.2...

MySQL で置換操作を使用したときにデータ損失が発生する問題の解決策

序文同社の開発者は、データの更新時に replace into ステートメントを使用していました。不...

複数の条件を持つ MySQL クエリ メソッド

複数の条件を持つ MySQL クエリ環境: MySQL 5.7 where ステートメントに複数の ...

webpackでvue環境を構築する際の異常なエラーを解決する

目次まず、package.jsonを設定します次にwebpackツールをインストールしますwebpa...