Решение этого полностью в чистом 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
в качестве разделителя полей устанавливается запятая. Это означает, что остальные строки в файле будут автоматически разделены запятыми на поля. Это используется в цикле во втором блоке для перебора полей CSV (от второго поля до последнего )в каждой строке.
Для каждой из других строк в данных он перебирает поля, разделенные запятыми -, и когда он находит поле, значение которого является строкой 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-адрес и номер порта один за другим.
Чтобы объединить их в полный сценарий:
#!/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-адреса открыто более одного порта, команда будет выполняться несколько раз для этого адреса.