запись того же результата для дублированных значений столбца - PullRequest
0 голосов
/ 17 марта 2020

Я действительно новичок в bash. У меня есть список доменов в файле .txt (URLs.txt). Я также хочу иметь файл .csv, который состоит из 3 столбцов, разделенных , (myFile.csv). Мой код читает каждую строку URLs.txt (каждый домен), находит его IP-адрес и затем вставляет их в myFile.csv (домен в первом столбце, его IP-адрес во 2-м столбце.

Name, IP
ex1.com, 10.20.30.40
ex2.com, 20.30.40.30 
ex3.com, 10.45.60.20 
ex4.com, 10.20.30.40

Здесь мой код:

echo "Name,IP" > myFile.csv   # let's overwrite, not appending
while IFS= read -r line; do
    ipValue=                            # initialize the value
    while IFS= read -r ip; do
        if [[ $ip =~ ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
            ipValue+="${ip}-"           # append the results with "-"
        fi
    done < <(dig +short "$line")        # assuming the result has multi-line
    ipValue=${ipValue%-}                # remove trailing "-" if any
    if [[ -n $ipValue ]]; then
                # if the IP is not empty
        echo "$line,$ipValue" >> myFile.csv
    fi
done < URLs.txt

Я хочу добавить еще один столбец в myFile.csv для хранения открытых портов каждого IP-адреса. Поэтому вывод будет выглядеть так:

Name, IP, Port
ex1.com, 10.20.30.40, 21/tcp 
ex2.com, 20.30.40.30, 20/tcp 
ex3.com, 10.45.60.20, 33/tcp 
ex4.com, 10.20.30.40, 21/tcp

Я хочу для этого используйте Nmap. После того, как я выбрал IP-адрес из 2-го столбца myFile.csv и нашел его открытые порты с помощью Nmap, я хочу записать результат Nmap в соответствующую ячейку 3-го столбца.

Кроме того, если во втором столбце есть другой аналогичный IP-адрес, я хочу написать результат Nmap и для этой строки. Я имею в виду, что не хочу снова запускать Nmap для дублированного IP-адреса. Например, в моем примере есть два «10.20.30.40» во 2-м столбце. Я хочу использовать Nmap только один раз и для 1-го «10.20.30.40» (а также записать результат для 2-го «10.20.30.40», Nmap не должен запускаться для дублированного IP).

Чтобы это произошло, я изменил первая строка моего кода:

echo "Name,IP,Port" > myFile.csv  

, а также вот код Nmap для поиска открытых портов:

    nmap -v -Pn -p 1-100 $ipValue -oN out.txt
    port=$(grep '^[0-9]' out.txt | tr '\n' '*' | sed 's/*$//')

, но я не знаю, что делать дальше и как применить эти изменения к моему коду.

Я обновил свой код до чего-то вроде этого:

echo "Name,IP" > myFile.csv   # let's overwrite, not appending
while IFS= read -r line; do
    ipValue=                            # initialize the value
    while IFS= read -r ip; do
        if [[ $ip =~ ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
            ipValue+="${ip}-"           # append the results with "-"
        fi
    done < <(dig +short "$line")        # assuming the result has multi-line
    ipValue=${ipValue%-}                # remove trailing "-" if any
    if [[ -n $ipValue ]]; then
                # if the IP is not empty
        nmap -v -Pn -p 1-100 $ipValue -oN out.txt
        port=$(grep '^[0-9]' out.txt | tr '\n' '*' | sed 's/*$//')
        echo "$line,$ipValue,$port" >> myFile.csv
    fi
done < URLs.txt

, но так Nmap использовался для поиска открытых портов дублированных IP-адресов. тоже, но я не хотел этого. Что мне делать?

1 Ответ

1 голос
/ 18 марта 2020

Вот модифицированная версия вашего скрипта, которая примерно выполняет то, что вы хотите:

#!/usr/bin/env bash

# cache maps from IP addresses to open ports
declare -A cache

getports() {
    local ip=$1
    nmap -v -Pn -p 1-100 "$ip" -oG - \
        | awk -F '\t' '
            /Ports:/ {
                n = split($2, a, /,? /)
                printf "%s", a[2]
                for (i = 3; i <= n; ++i)
                    printf ":%s", a[i]
            }
        '
}

{
    echo 'Name,IP,Port'

    while IFS= read -r url; do
        # Read filtered dig output into array
        readarray -t ips < <(dig +short "$url" | grep -E '^([0-9]+\.){3}[0-9]+$')

        # Build array of open ports
        unset ports
        for ip in "${ips[@]}"; do
            ports+=("${cache["$ip"]:=$(getports "$ip")}")
        done

        # Output
        printf '%s,%s,%s\n' \
            "$url" \
            "$(IFS='-'; echo "${ips[*]}")" \
            "$(IFS='-'; echo "${ports[*]}")"
    done < URLs.txt
} > myFile.csv

Строка readarray считывает отфильтрованный вывод из dig в массив IP-адресов; если этот массив имеет нулевую длину, остальная часть l oop пропускается.

Затем для каждого элемента в массиве ips мы получаем порты. Чтобы не вызывать nmap, если мы видели IP-адрес ранее, мы используем расширение ${<em>parameter</em>:=<em>word</em>} : если ${cache["$ip"]} не пусто, используйте его, в противном случае вызовите функцию getports и сохраните вывод в ассоциативном массиве cache.

getports вызывается для IP-адресов, которые мы не видели раньше; Я использовал -oG (" grepable output ") для облегчения анализа. Команда awk фильтрует строки, содержащие Ports:, которые выглядят как

Host: 52.94.225.242 ()  Ports: 80/open/tcp//http///     Ignored State: closed (99)

с полями, разделенными табуляцией. Затем мы разбиваем второе поле на регулярное выражение /,? / (необязательная запятая, за которой следует пробел) и сохраняем все, кроме первого поля результирующего массива, разделенного двоеточием.

Наконец, мы печатаем строку Данные CSV; если ips или ports содержат более одного элемента, мы хотим объединить элементы с помощью -, что достигается установкой IFS в подстановке команд и последующей печатью массивов с помощью [*].

Начальные echo и l oop сгруппированы в фигурные скобки, поэтому перенаправление вывода должно произойти только один раз.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...