LinuxでAWK言語を使用してテキストを操作する方法
序章
Linuxユーティリティは、多くの場合、Unixの設計哲学に従います。 ツールは小さく、入力と出力にプレーンテキストファイルを使用し、モジュール方式で動作することをお勧めします。 このレガシーにより、sedやawk
などのツールを使用した優れたテキスト処理機能があります。
awk
は、非常に便利な方法でテキストデータを操作するために使用できるプログラミング言語とテキストプロセッサの両方です。 このガイドでは、awk
コマンドラインツールの使用方法と、それを使用してテキストを処理する方法について説明します。
インタラクティブターミナルを起動します!
基本構文
awk
コマンドは、すべての最新のLinuxシステムにデフォルトで含まれているため、使用を開始するためにインストールする必要はありません。
awk
は、予測可能な方法でフォーマットされたテキストファイルを処理する場合に最も役立ちます。 たとえば、表形式のデータの解析と操作に優れています。 行ごとに動作し、ファイル全体を反復処理します。
デフォルトでは、フィールドを区切るために空白(スペース、タブなど)を使用します。 幸い、Linuxシステム上の多くの構成ファイルはこの形式を使用しています。
awk
コマンドの基本的な形式は次のとおりです。
awk '/search_pattern/ { action_to_take_on_matches; another_action; }' file_to_parse
awk
コマンドでは、検索部分またはアクション部分のいずれかを省略できます。 デフォルトでは、「アクション」部分が指定されていない場合に実行されるアクションは「印刷」です。 これは、一致するすべての行を単に印刷します。
検索部分が指定されていない場合、awk
は各行にリストされているアクションを実行します。
両方が指定されている場合、awk
は検索部分を使用して、現在の行がパターンを反映しているかどうかを判断し、一致するアクションを実行します。
最も単純な形式では、cat
のようなawk
を使用して、テキストファイルのすべての行を画面に出力できます。
友達のグループの好きな食べ物をリストしたfavorite_food.txt
ファイルを作成します。
echo "carrot sandy wasabi luke sandwich brian salad ryan spaghetti jessica" > favorite_food.txt
次に、awk
コマンドを使用して、ファイルを画面に出力します。
awk '{print}' favorite_food.txt
画面にファイルが印刷されます。
Outputcarrot sandy wasabi luke sandwich brian salad ryan spaghetti jessica
これはあまり役に立ちません。 ファイルを検索して「sand」というテキストを検索することにより、awk
の検索フィルタリング機能を試してみましょう。
awk '/sand/' favorite_food.txt
Outputcarrot sandy sandwich brian
ご覧のとおり、awk
は、「砂」の文字が含まれている行のみを印刷するようになりました。
正規表現を使用すると、テキストの特定の部分をターゲットにすることができます。 「sand」の文字で始まる行のみを表示するには、正規表現^sand
を使用します。
awk '/^sand/' favorite_food.txt
今回は、次の1行のみが表示されます。
Outputsandwich brian
同様に、アクションセクションを使用して、印刷する情報を指定できます。 たとえば、最初の列のみを印刷するには、次のコマンドを使用します。
awk '/^sand/ {print $1;}' favorite_food.txt
Outputsandwich
列番号に関連付けられた変数によって、(空白で区切られた)すべての列を参照できます。 たとえば、最初の列は$1
、2番目の列は$2
であり、$0
で行全体を参照できます。
内部変数と拡張フォーマット
awk
コマンドは、ファイルを処理するときに、いくつかの内部変数を使用して特定の情報を割り当てます。
awk
が使用する内部変数は次のとおりです。
- FILENAME :現在の入力ファイルを参照します。
- FNR :現在の入力ファイルを基準にした現在のレコードの番号を参照します。 たとえば、入力ファイルが2つある場合、合計ではなく、各ファイルのレコード数がわかります。
- FS :レコード内の各フィールドを示すために使用される現在のフィールドセパレータ。 デフォルトでは、これは空白に設定されています。
- NF :現在のレコードのフィールド数。
- NR :現在のレコードの番号。
- OFS :出力データのフィールドセパレータ。 デフォルトでは、これは空白に設定されています。
- ORS :出力データのレコードセパレータ。 デフォルトでは、これは改行文字です。
- RS :入力ファイル内の個別のレコードを区別するために使用されるレコード区切り文字。 デフォルトでは、これは改行文字です。
これらの変数の値は、ファイルのニーズに合わせて自由に変更できます。 通常、これは処理の初期化フェーズで行います。
これは私たちに別の重要な概念をもたらします。 awk
構文は、これまでに使用したものよりも少し複雑です。オプションのBEGIN
およびEND
ブロックもあり、ファイル処理の前後に実行するコマンドを含めることができます。 、 それぞれ。
これにより、拡張構文は次のようになります。
awk 'BEGIN { action; } /search/ { action; } END { action; }' input_file
BEGIN
およびEND
キーワードは、検索パラメーターと同様に、特定の条件のセットです。 これらは、ドキュメントが処理される前後で一致します。
これは、BEGIN
セクションでいくつかの内部変数を変更できることを意味します。 たとえば、/etc/passwd
ファイルは、空白ではなくコロン(:
)で区切られます。
このファイルの最初の列を印刷するには、次のコマンドを実行します。
awk 'BEGIN { FS=":"; } { print $1; }' /etc/passwd
Outputroot daemon bin sys sync games man . . .
BEGIN
およびEND
ブロックを使用して、印刷しているフィールドに関する情報を印刷できます。 次のコマンドを使用して、データをファイルからテーブルに変換し、\t
を使用してタブの間隔を適切に設定します。
awk 'BEGIN { FS=":"; print "User\t\tUID\t\tGID\t\tHome\t\tShell\n--------------"; } {print $1,"\t\t",$3,"\t\t",$4,"\t\t",$6,"\t\t",$7;} END { print "---------\nFile Complete" }' /etc/passwd
次の出力が表示されます。
OutputUser UID GID Home Shell -------------- root 0 0 /root /bin/bash daemon 1 1 /usr/sbin /bin/sh bin 2 2 /bin /bin/sh sys 3 3 /dev /bin/sh sync 4 65534 /bin /bin/sync . . . --------- File Complete
ご覧のとおり、awk
の機能のいくつかを利用することで、非常にうまくフォーマットできます。
展開された各セクションはオプションです。 実際、別のセクションが定義されている場合、メインアクションセクション自体はオプションです。 たとえば、次のようなことができます。
awk 'BEGIN { print "We can use awk like the echo command"; }'
そして、次の出力が表示されます。
OutputWe can use awk like the echo command
次に、出力のフィールド内でテキストを検索する方法を見てみましょう。
フィールド検索と複合式
前の例の1つでは、「sand」で始まるfavorite_food.txt
ファイルの行を印刷しました。 行全体の先頭を探していたので、これは簡単でした。
代わりにフィールドの先頭で検索パターンが一致したかどうかを知りたい場合はどうなりますか?
favorite_food.txt
ファイルの新しいバージョンを作成して、各人の食べ物の前にアイテム番号を追加します。
echo "1 carrot sandy 2 wasabi luke 3 sandwich brian 4 salad ryan 5 spaghetti jessica" > favorite_food.txt
このファイルから「sa」で始まるすべての食品を検索する場合は、次のようなものを試すことから始めることができます。
awk '/sa/' favorite_food.txt
これにより、「sa」を含むすべての行が表示されます。
Output1 carrot sandy 2 wasabi luke 3 sandwich brian 4 salad ryan
ここでは、単語内の「sa」の任意のインスタンスに一致しています。 これには、中央にパターンがある「わさび」や、目的の列にない「砂」などが含まれることになります。 この場合、second列に「sa」が含まれるbeginningという単語にのみ関心があります。
次のコマンドを使用して、awk
に2番目の列の先頭でのみ一致するように指示できます。
awk '$2 ~ /^sa/' favorite_food.txt
ご覧のとおり、これにより、2番目の列の先頭でのみ一致するものを検索できます。
field_num ~
の部分は、awk
が2番目の列にのみ注意を払う必要があることを指定しています。
Output3 sandwich brian 4 salad ryan
「!」を含めることで、一致しないものを簡単に検索できます。 チルダの前の文字(〜)。 このコマンドは、「sa」で始まる食べ物がないすべての行を返します。
awk '$2 !~ /^sa/' favorite_food.txt
Output1 carrot sandy 2 wasabi luke 5 spaghetti jessica
後で「sa」で始まらない行のみに関心があり、アイテム番号が5未満であると判断した場合は、次のような複合式を使用できます。
awk '$2 !~ /^sa/ && $1 < 5' favorite_food.txt
これにより、いくつかの新しい概念が導入されます。 1つ目は、&&
演算子を使用して、一致する回線の要件を追加する機能です。 これを使用して、ラインが一致するように任意の数の条件を組み合わせることができます。 この場合、この演算子を使用して、最初の列の値が5未満であることを確認するチェックを追加しています。
次の出力が表示されます。
Output1 carrot sandy 2 wasabi luke
awk
を使用してファイルを処理できますが、他のプログラムの出力を操作することもできます。
他のプログラムからの出力の処理
ファイル名を指定する代わりに、awk
コマンドを使用して、他のプログラムの出力を解析できます。 たとえば、awk
を使用して、ip
コマンドからIPv4アドレスを解析できます。
ip a
コマンドは、IPアドレス、ブロードキャストアドレス、およびマシン上のすべてのネットワークインターフェイスに関するその他の情報を表示します。 eth0
というインターフェイスの情報を表示するには、次のコマンドを使用します。
ip a s eth0
次の結果が表示されます。
Output2571: eth0@if2572: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default link/ether 02:42:ac:11:00:0b brd ff:ff:ff:ff:ff:ff link-netnsid 0 inet 172.17.0.11/16 brd 172.17.255.255 scope global eth0 valid_lft forever preferred_lft forever
awk
を使用してinet
行をターゲットにしてから、IPアドレスだけを出力できます。
ip a s eth0 | awk -F '[\/ ]+' '/inet / {print $3}'
-F
フラグは、正規表現[\/ ]+
を使用して、スラッシュまたはスペースで区切るようにawk
に指示します。 これにより、行 inet 172.17.0.11/16
が別々のフィールドに分割されます。 スペースとスラッシュで区切っているため、行の先頭のスペースもフィールドとしてカウントされるため、IPアドレスは3番目のフィールドにあります。 この場合、awk
は連続するスペースを単一のスペースとして扱うことに注意してください。
出力にはIPアドレスが表示されます。
Output172.17.0.11
awk
を使用して他のコマンドの出力を検索または解析できる場所はたくさんあります。
結論
これで、awk
コマンドを使用して、テキストファイルとテキストストリームを操作、フォーマット、および選択的に印刷する方法の基本を理解できたはずです。 ただし、Awkははるかに大きなトピックであり、実際には、変数の割り当て、制御構造、組み込み関数などを備えたプログラミング言語全体です。 独自のスクリプト内で使用して、信頼できる方法でテキストをフォーマットできます。
awk
の詳細については、その作成者による無料のパブリックドメインの本を読むことができます。