sedまたはawkを再度呼び出さずに、文字列からドット文字を削除するにはどうすればよいですか?


12

次のhostlist.txtようなテキストを含むというファイルがあります。

host1.mydomain.com
host2.mydomain.com
anotherhost
www.mydomain.com
login.mydomain.com
somehost
host3.mydomain.com

次の小さなスクリプトがあります。

#!/usr/local/bin/bash

while read host; do
        dig +search @ns1.mydomain.com $host ALL \
        | sed -n '/;; ANSWER SECTION:/{n;p;}';
done <hostlist.txt \
        | gawk '{print $1","$NF}' >fqdn-ip.csv

出力先fqdn-ip.csv

host1.mydomain.com.,10.0.0.1
host2.mydomain.com.,10.0.0.2
anotherhost.internal.mydomain.com.,10.0.0.11
www.mydomain.com.,10.0.0.10
login.mydomain.com.,10.0.0.12
somehost.internal.mydomain.com.,10.0.0.13
host3.mydomain.com.,10.0.0.3

私の質問は.、コンマの直前を削除せずsedgawk再度呼び出すことはできませんか?ドットを取り除く既存の呼び出しsedまたはgawk呼び出しで実行できるステップはありますか?

hostlist.txt 数千のホストが含まれるので、スクリプトを高速かつ効率的にしたいです。


2
dig +shortうまくいかない理由は何ですか?
ロジャーリップスコム

@RogerLipscombe。これは、hostlist.txtのホストの一部がFQDNではなく単なるホスト名であるため、+ searchを使用して解決するためです。
リノーブ

回答:


18

sedコマンド、awkコマンド、および後続期間の除去は全て単一AWKコマンドに組み合わせることができます。

while read -r host; do dig +search "$host" ALL; done <hostlist.txt | awk 'f{sub(/.$/,"",$1); print $1", "$NF; f=0} /ANSWER SECTION/{f=1}'

または、複数の行に広がるように:

while read -r host
do
    dig +search "$host" ALL
done <hostlist.txt | awk 'f{sub(/.$/,"",$1); print $1", "$NF; f=0} /ANSWER SECTION/{f=1}'

awkコマンドはdoneステートメントの後に続くため、1つのawkプロセスのみが呼び出されます。ここでは効率は重要ではありませんが、これは各ループで新しいsedまたはawkプロセスを作成するよりも効率的です。

このテストファイルでは:

$ cat hostlist.txt 
www.google.com
fd-fp3.wg1.b.yahoo.com

コマンドは以下を生成します。

$ while read -r host; do dig +search "$host" ALL; done <hostlist.txt | awk 'f{sub(/.$/,"",$1); print $1", "$NF; f=0} /ANSWER SECTION/{f=1}'
www.google.com, 216.58.193.196
fd-fp3.wg1.b.yahoo.com, 206.190.36.45

使い方

awkは、入力を一度に1レコード(行)暗黙的に読み取ります。このawkスクリプトは、単一の変数を使用します。fこれは、前の行が回答セクションのヘッダーであったかどうかを示します。

  • f{sub(/.$/,"",$1); print $1", "$NF; f=0}

    前の行が回答セクションのヘッダーであった場合、ftrueになり、中括弧内のコマンドが実行されます。最初は、最初のフィールドから末尾のピリオドを削除します。2番目は最初のフィールドを印刷し,、その後に、最後のフィールドが続きます。3番目のステートメントfはゼロ(false)にリセットされます。

    つまり、fここは論理条件として機能します。中括弧内のコマンドfは、ゼロ以外の場合に実行されます(awkでは「true」を意味します)。

  • /ANSWER SECTION/{f=1}

    現在の行に文字列が含まれている場合、ANSWER SECTION変数f1(true)に設定されます。

    ここで/ANSWER SECTION/は、論理条件として機能します。現在が正規表現と一致する場合、trueと評価されますANSWER SECTION。存在する場合、中括弧で囲まれたコマンドが実行されます。


@ John1024ありがとう!awkがループ内にある必要はないことを知りませんでした(最後の行が外側にある場合にのみ機能すると考えました)。あるf任意の変数またはあるf{}AWKの機能の明示的な部分?
リノーブ

どういたしまして。 fは任意の変数です。実際には、{}複雑な論理条件の前に置くことができます。 fは非常に単純な論理条件です。非ゼロの場合はtrue、ゼロの場合はfalseです。
ジョン1024

@Linoob 2番目のコマンドでは、最初のコマンドでの/ANSWER SECTION/役割に似た論理条件の役割を果たしていることに注意してくださいf。これを議論するために答えを更新しました。
ジョン1024

7

digホスト名のリストを含むファイルを読み取り、それらを1つずつ処理できます。dig回答セクション以外のすべての出力を抑制するように指示することもできます。

これにより、必要な出力が得られます。

dig -f hostlist.txt +noall +answer +search | 
    awk '{sub(/\.$/,"",$1); print $1","$5}'

awksub()関数は.、最初のフィールドの終わりからリテラルのピリオドを取り除くために使用されます。次に、awkフィールド1と5をコンマで区切って印刷します。

注:hostlist.txt解決しないエントリは完全に破棄されます-stdoutまたはstderrには表示されません。

(LinuxおよびFreeBSDでテスト済み)


6

の呼び出しをgawk次のように変更します。

| gawk '{print substr($1,1,length($1)-1)","$NF}' >fqdn-ip.csv
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.