これは私のサンプルファイルです。実際のデータにはより多くのデータが含まれています。
wolf@linux:~$ more log*
::::::::::::::
log1.csv
::::::::::::::
hostname,sn,type,ip,random
abc,a11,zzz,192.168.168.168,rrr
def,e16,yyy,192.168.168.169,fff
ghi,k16,yyy,192.168.168.170,ggg
::::::::::::::
log2.csv
::::::::::::::
hostname,sn,ip,random
abc,a11,192.168.168.168,rrr
def,e16,192.168.168.169,fff
ghi,k16,yyy,192.168.168.170,ggg
wolf@linux:~$
ホスト名などの一部のデータは、常に最初の列にあります。だから、それらを得るのは簡単です。awk -F, '{print $1}'
wolf@linux:~$ awk -F, '{print $1, $4}' log*
hostname ip
abc 192.168.168.168
def 192.168.168.169
ghi 192.168.168.170
hostname random
abc rrr
def fff
ghi 192.168.168.170
wolf@linux:~$
問題は、IPアドレスなどのデータがログファイルのデータによって異なる列にあることです。
grepを使用してホスト名とIP列のみを取得するにはどうすればよいですか?
wolf@linux:~$ awk -F, '/def/ {print $1, $4}' log*
def 192.168.168.169
def fff
wolf@linux:~$
。
wolf@linux:~$ awk -F, '/def/ {print $1, $3}' log*
def yyy
def 192.168.168.169
wolf@linux:~$
希望の出力
def 192.168.168.169
def 192.168.168.169
答え1
データフィールドが各ファイルのヘッダー行の後にある場合は、次のことができます。
awk -F, 'FNR==1{ for(i=1; i<=NF; i++) if($i=="ip") break; next }
{ print $1, $i }' log*.csv
答え2
私は次のものを持って来ることを願っています:
awk -F, '{for(i=2;i<=NF;i++) if ( $i ~ /^192/ ) printf "%s %s\n",$1,$i ;}'
どこ
- IPが192で始まると思います。
ホスト名は関連フィールド1にあります。- IPが2つ以上の場合、行は2回印刷されます。
以下を使用してIPをさらに制限することができますif ( $i ~ /^[0-9\.]+$/ )
(12個もキャプチャされます)。
答え3
使用csvkit
:
$ csvcut -c hostname,ip log1.csv
hostname,ip
abc,192.168.168.168
def,192.168.168.169
ghi,192.168.168.170
$ csvcut -c hostname,ip log2.csv
hostname,ip
abc,192.168.168.168
def,192.168.168.169
ghi,yyy
このcsvcut
コマンドは標準cut
コマンドとやや似ていますが、ヘッダー情報を使用して名前付き列を抽出できます。
これは実際に正しい各ファイルのヘッダーに依存します。
答え4
ヘッダーを持つファイルがある場合は、通常、最初にf[]
下の配列に格納されているフィールド(列)の順序のヘッダータグ(名前)マッピングを作成するのが最善です。その後、フィールドでインデックス付けされた配列を簡単に逆参照できます。フィールド値名を取得します。これにより、各入力ファイルの列の順序に関係なく、スクリプトが正しく機能します。
$ cat tst.awk
BEGIN { FS="," }
FNR==1 {
delete f
for (i=1; i<=NF; i++) {
f[$i] = i
}
next
}
$(f["hostname"]) == h { print $(f["hostname"]), $(f["ip"]) }
$ awk -v h='def' -f tst.awk log*.csv
def 192.168.168.169
def 192.168.168.169