次のようなテキストを含む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
私の質問は、カンマの直前の.
をどのように削除するかですなしsed
またはgawk
を再度呼び出す?ドットを取り除く既存のsed
またはgawk
呼び出しで実行できる手順はありますか?
hostlist.txt
には数千のホストが含まれるため、スクリプトを高速かつ効率的にしたいと思います。
sed
コマンド、awk
コマンド、および後続期間の削除は、すべて1つの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
ステートメントの後に続くため、呼び出されるawk
プロセスは1つだけです。ここでは効率は重要ではないかもしれませんが、これは各ループで新しい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}
前の行が回答セクションのヘッダーだった場合、f
はtrueになり、中括弧で囲まれたコマンドが実行されます。最初は、最初のフィールドから後続期間を削除します。 2番目は、最初のフィールドを印刷し、その後に_,
_、最後のフィールドを印刷します。 3番目のステートメントは、f
をゼロ(false)にリセットします。
つまり、ここでのf
は論理条件として機能します。中括弧内のコマンドは、f
がゼロ以外の場合に実行されます(これは、awkでは「true」を意味します)。
_/ANSWER SECTION/{f=1}
_
現在の行に文字列_ANSWER SECTION
_が含まれている場合、変数f
は_1
_(true)に設定されます。
ここで、_/ANSWER SECTION/
_は論理条件として機能します。現在が正規表現_ANSWER SECTION
_に一致する場合、trueと評価されます。含まれている場合は、中括弧で囲まれたコマンドが実行されます。
Dig
は、ホスト名のリストを含むファイルを読み取り、それらを1つずつ処理できます。 Dig
に、回答セクション以外のすべての出力を抑制するように指示することもできます。
これにより、必要な出力が得られます。
_Dig -f hostlist.txt +noall +answer +search |
awk '{sub(/\.$/,"",$1); print $1","$5}'
_
awk
のsub()
関数は、最初のフィールドの終わりからピリオド_.
_を削除するために使用されます。次に、awk
は、フィールド1と5をコンマで区切って出力します。
注:解決しない_hostlist.txt
_のエントリは完全に破棄されます-それらはstdoutに表示されませんOR stderr。
(LinuxおよびFreeBSDでテスト済み)
gawk
の呼び出しを次のように変更します。
| gawk '{print substr($1,1,length($1)-1)","$NF}' >fqdn-ip.csv