テキストファイルがあります。それは次のようになります:
www.ac.com has address 6.1.1.146 www.ac.com is an alias for ac.com. www.ac.com is an alias for ac.com.
www.ba.net is an alias for www-bn.gs.ba.com. www-bn.gs.ba.com has address 11.28.11.4 ;; connection timed out; no servers could be reached
has address
の前後の列を抽出し、カンマで区切りたい。だから私は取得したい:
www.ac.com,6.1.1.146
www-bn.gs.ba.com,11.28.11.4
これを行う方法? awk '{print $1,$4}' myfile > newfile
を試しましたが、1列目と4列目にあるとは限らないため、うまく機能しませんでした。対象の列はさまざまですが、常にhas address
で区切られています。
grep
とsed
の使用:
grep -o '[^ ]* has address [^ ]*' | sed 's/ has address /,/'
とても簡単なので、私はこれが好きです。
説明:
grep
は、次のパターンを見つけた各行の一致する(-o
)部分のみを出力します。
[^ ]*
)の後にhas address
が続き、その後にスペースではない文字([^ ]*
)が続きます。sed
は単にhas address
を,
に置き換えます
sed
:
sed -r 's/(.* |^)([^ ]*) has address ([^ ]*)( .*|$)/\2,\3/' myfile > newfile
sed -r 's/foo/bar/' myfile > newfile
:「拡張正規表現」(-r
)でsed
を使用するため、以下のキャプチャグループ()
をエスケープする必要はありません。 foo
の出現箇所をbar
に置き換えます。 myfile
から読み取り、newfile
に書き込みます。(.* |^)([^ ]*) has address ([^ ]*)( .*|$)
:スペースの前後にある文字列has address
を探します。この前後は、スペースを含まない文字列である必要があり、グループ([^ ]*)
でキャプチャする必要があります。先頭の単語の前は、スペース(前に.*
)または行の先頭((.* |^)
)のいずれかである必要があります。次の単語の後には、スペース(その後に.*
が続く)、または行の終わり、つまり( .*|$)
のいずれかである必要があります。\2,\3
:上記の式は行全体をキャプチャするため、2番目と3番目のキャプチャグループ、つまりhas address
の前後の単語に置き換えます。Perl -nE '/(\S+) has address (\S+)/ and say "$1,$2"' x
awk
:
awk -v OFS=, '
{
for(i=1;i<NF;i++){
j=i+1;
if ($i=="has" && $j=="address") {
domain=i-1;
ip=i+2;
print $domain,$ip;
break;
}
}
}'
フィールドをループし、「has」が見つかり、次のフィールドが「address」の場合、出力フィールドセパレータとして,
を使用して前後のフィールドを出力します。