web-dev-qa-db-ja.com

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

次のようなテキストを含む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には数千のホストが含まれるため、スクリプトを高速かつ効率的にしたいと思います。

12
Linoob

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と評価されます。含まれている場合は、中括弧で囲まれたコマンドが実行されます。

18
John1024

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

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

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

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

注:解決しない_hostlist.txt_のエントリは完全に破棄されます-それらはstdoutに表示されませんOR stderr。

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

7
cas

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

| gawk '{print substr($1,1,length($1)-1)","$NF}' >fqdn-ip.csv
6
DopeGhoti