IPアドレスと開いているポートを含むCSVファイルがあります。
IP,1,3,4,6,7,9,13,17,19,20,21,22,23,24,25,26
1.1.1.2,,,,,,,,,,,open,,,,,
1.1.1.3,,,,,,,,,,,open,,,,,
1.1.1.4,,open ,open,,,,,,,,open,,,,,
1.1.1.5,,,,,,,,,,,open,,,,,
1.2.3.4,,,,,,,,,,,open,,,,,
1.4.5.6,,,,,open,,,,,,open,,,,,
1.4.5.6,,,,,,,,,,,open,,,,,
1.1.3.4,,,,,,,,,,,open,,,,,
開いているポートを持つ各IPアドレスに対して、IPアドレスと開いているポートのポート番号(CSVヘッダーから取得)を使用してコマンドを実行する必要があります。
答え1
この問題を解決する完全純粋にアクセスすることは望ましくないと思いますbash
。たとえば、質問を参照してください。シェルループを使用してテキストを処理するのはなぜ悪い習慣と見なされますか?」。
代わりに、入力データを理解しやすくしましょう。
awk 'FNR == 1 { split($0, port, ","); FS=","; next }
{ for (i=2; i<=NF; ++i) if ($i == "open") print $1, port[i] }' file.csv
このawk
コマンドは最初にCSVファイルの最初の行にあるポート番号を配列に読み込みますport
。その列のポート番号N
はに保存されますport[N]
。
入力の最初の行をコンマで区切り、結果を配列に保存してこれを行いますport
。これがsplit()
コマンドが行うことです。条件はFNR == 1
、「これがファイルの最初の行である場合は、次のようにしてください...」(FNR
現在の入力ファイルの行番号)を意味します。各入力行に対して無条件のコードブロックが実行される。
を呼び出しsplit()
た後、FS
フィールド区切り文字はコンマに設定されます。つまり、ファイルの他の行は自動的にフィールドでコンマで区切られます。これは、2番目のブロックのループで各行のCSVフィールド(2番目のフィールドから最後のフィールドまで)を繰り返すために使用されます。
データの他のすべての行に対してカンマ区切りのフィールドを繰り返し、値が文字列のフィールドを見つけたら、open
IPアドレス(最初のフィールド)とそのポート番号を印刷します。
質問のデータを考慮すると、このコマンドの出力は次のようになります。
1.1.1.2 21
1.1.1.3 21
1.1.1.4 4
1.1.1.4 21
1.1.1.5 21
1.2.3.4 21
1.4.5.6 7
1.4.5.6 21
1.4.5.6 21
1.1.3.4 21
これはシェルのループを通して簡単に読むことができます。
while read -r ip port; do
telnet "$ip" "$port" # or whatever your command is
done
これにより、IPアドレスとポート番号が1つずつ読み込まれます。
これを完全なスクリプトに結合するには:
#!/bin/sh
awk 'FNR == 1 { split($0, port, ","); FS=","; next }
{ for (i=2; i<=NF; ++i) if ($i == "open") print $1, port[i] }' file.csv |
while read -r ip port; do
telnet "$ip" "$port" # or whatever your command is
done
コマンドの出力は、値を読み取り、コマンドを呼び出すループawk
にパイプされます(入力ファイル名の後にパイプがあります)。while
|
IPアドレスに複数のポートが開いている場合、このコマンドはそのアドレスに対して複数回実行されます。
答え2
使用最初と次の対応するフィールドを選択しますawk
。
awk -d "," -F '{print $1, $n...}