2

Привет у меня есть скрипт, и в нем мне нужно получить имена хостов из IP-адресов, которые генерирует скрипт. Сценарий сгенерирует эти IP-адреса в 1 аккуратный файл с одним столбцом. Это буквально просто IP-адрес (1 для каждой строки). У меня есть еще один файл с именем 'db', который выглядит так:

IP Hostname

'db' - это моя база данных, в которой хранится список IP-адресов и имен хостов, которые делегированы этим IP-адресам. Это статические адреса, которые не меняются, обычно это серверы или коммутаторы и т.д. Что мне нужно для IP-адресов, которые генерирует сценарий, я хотел бы разрешить их с помощью имен ПЕРВЫХ хостов из этого файла базы данных, и если это не так найдите его там, затем выполните команду host . Я уже делаю последнее с host но я действительно хочу, чтобы они исходили из моего файла БД. Окончательный вывод должен быть только 1 файл с 1 столбцом имен хостов. У меня есть какие-то идеи по использованию awk с массивами, но я не могу получить именно то, что мне нужно.

1 ответ1

6

grep - команда, основная цель которой состоит в том, чтобы просматривать текст на предмет наличия паттерна (или паттернов).  Его упрощенное приложение для этой задачи будет

grep 1.2.3.4 db

который будет выводить строку IP_address Hostname () из файла db , которые соответствуют шаблону 1.2.3.4  Обратите внимание, что я сказал строку (а) (а не строку) и соответствовал шаблону (а не содержал строку), потому что здесь есть пара ошибок.

  • Одним из них является то, что grep , как я уже сказал, (по умолчанию) ищет шаблоны, а не строки.  Эти шаблоны называются регулярными выражениями , и существует множество документации по ним.  Самый важный факт о регулярных выражениях для этой дискуссии - это период » . ”- это шаблон, который соответствует любому отдельному символу.  Так, например, шаблон (регулярное выражение) 1.2.3.4 будет соответствовать строкам 132.364 и 1a2b3c4 .  Скорее всего, это не проблема для столбца IP_address , но такие строки могут появиться в столбце Hostname.
  • Другое - то, что, если не указано иное, grep ищет предоставленный шаблон в любом месте строки.  Таким образом, шаблон 1.2.3.4 будет соответствовать линиям, содержащим 31.2.3.4 и 1.2.3.42 .

Но я верю, что вы сделаете хорошую работу, чтобы получить нужную строку - и только эту строку - с помощью команды

grep "^1.2.3.4[[:space:]]" db

где

  • « ^ » - это другой символ, который является особенным в регулярных выражениях; это означает, что этот шаблон должен появиться в начале строки.
  • « [[:space:]] » представляет пробельный символ; либо пробел или табуляция.  Если вы уверены, что ваш файл db использует только пробелы, вы можете просто найти пробел; например,

    grep "^1.2.3.4 " db
    

Они по-прежнему найдут строки, начинающиеся с 132.364 или 1a2b3c4 .  Но если ваш db файл правильно структурирован, у вас не должно быть таких строк в начале строк вашего db файла.

Вы можете помешать » . ”Из сопоставления произвольных символов с любым из следующих:

  • grep "^1\.2\.3\.4[[:space:]]" db
  • grep "^1\.2\.3\.4 " db
  • grep -F "1.2.3.4 " db

но первые два потребуют от вас перескочить через обручи в вашем скрипте, чтобы преобразовать 1.2.3.4 в 1\.2\.3\.4 , а третий уберет специальное значение « ^ » (поэтому 31.2.3.4 будет все еще совпадают).

Как указано выше, все эти команды соответствуют всей строке из файла db которая соответствует IP-адресу.  Чтобы получить только имя хоста (второй столбец), используйте

grep "^1.2.3.4[[:space:]]" db | awk '{print $2}'

Это просто запишет имя хоста в стандартный вывод (как правило, на экран).  Более полезная операция в сценарии будет

db_host=$(grep "^1.2.3.4[[:space:]]" db | awk '{print $2}')

который захватывает этот вывод в переменную оболочки db_host .

Итак, наконец, этот раздел вашего скрипта может выглядеть примерно так:

db_host=$(grep "^$this_IP_address[[:space:]]" db | awk '{print $2}')
if [ "$db_host" = "" ]
then
    Use the host command.
          ︙
fi

который вы бы поместили в цикл, где переменная this_IP_address принимает каждый IP-адрес, который вы хотите обработать.  Если они есть в файле (т. Е. В другом файле, отдельном от db), прочитайте этот файл по одной строке за раз.

Например, если у вас есть IP-адреса (по одному на строку) в файле с именем src_ip , и все, что вам нужно сделать, это записать имена хостов в стандартный вывод, вы можете сказать:

while read this_IP_address
do
    db_host=$(grep "^$this_IP_address[[:space:]]" db | awk '{print $2}')
    if [ "$db_host" = "" ]
    then
        # Use the host command to lookup $this_IP_address.
        host "$this_IP_address" | head -n 1 | awk '{print $5}'
    else
        echo "$db_host"
    fi
done < src_ip

grep -f src_ip db не будет особенно полезен для описываемой вами проблемы (если я правильно понимаю), потому что он будет сообщать обо всех строках в db которые соответствуют любому IP-адресу в src_ip - оставляя вам возможность выяснить, какие IP-адреса не были сопоставлены.


Более простой способ сделать это пришло мне в голову:

awk -v this_one="$this_IP_address" '$1 == this_one {print $2}' db

который копирует переменную оболочки this_IP_address в переменную awk this_one а затем говорит «напечатать второе поле любой строки, первое поле которой равно this_one ».  Это один процесс, а не два, и он устраняет проблему « . Сопоставление произвольных символов.  Оберните его в db_host=$(…) как и раньше.

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .