Как удалить символ точки из строки без повторного вызова sed или awk?


12

У меня есть файл с именем, hostlist.txtкоторый содержит такой текст:

host1.mydomain.com
host2.mydomain.com
anotherhost
www.mydomain.com
login.mydomain.com
somehost
host3.mydomain.com

У меня есть следующий маленький скрипт:

#!/usr/local/bin/bash

while read host; do
        dig +search @ns1.mydomain.com $host ALL \
        | sed -n '/;; ANSWER SECTION:/{n;p;}';
done <hostlist.txt \
        | gawk '{print $1","$NF}' >fqdn-ip.csv

Какие выходы для fqdn-ip.csv:

host1.mydomain.com.,10.0.0.1
host2.mydomain.com.,10.0.0.2
anotherhost.internal.mydomain.com.,10.0.0.11
www.mydomain.com.,10.0.0.10
login.mydomain.com.,10.0.0.12
somehost.internal.mydomain.com.,10.0.0.13
host3.mydomain.com.,10.0.0.3

У меня вопрос: как удалить .запятую перед запуском без вызова sedили gawkснова? Есть ли какой-то шаг, который я могу выполнить в существующих sedили gawkвызовах, которые уберут точку?

hostlist.txt будет содержать тысячи хостов, поэтому я хочу, чтобы мой скрипт был быстрым и эффективным.


2
Любая причина, почему у dig +shortвас не работает?
Роджер Липскомб

@RogerLipscombe, потому что некоторые хосты в моем hostlist.txt - это просто имена хостов, а не FQDN, поэтому я использую + search для их разрешения.
Linoob

Ответы:


18

Команда sed, awkкоманда и удаление завершающего периода могут быть объединены в одну команду awk:

while read -r host; do dig +search "$host" ALL; done <hostlist.txt | awk 'f{sub(/.$/,"",$1); print $1", "$NF; f=0} /ANSWER SECTION/{f=1}'

Или, как разбито на несколько строк:

while read -r host
do
    dig +search "$host" ALL
done <hostlist.txt | awk 'f{sub(/.$/,"",$1); print $1", "$NF; f=0} /ANSWER SECTION/{f=1}'

Поскольку awkкоманда следует за doneоператором, awkвызывается только один процесс. Хотя эффективность здесь не имеет значения, это более эффективно, чем создание нового процесса sed или awk с каждым циклом.

пример

С этим тестовым файлом:

$ cat hostlist.txt 
www.google.com
fd-fp3.wg1.b.yahoo.com

Команда выдает:

$ while read -r host; do dig +search "$host" ALL; done <hostlist.txt | awk 'f{sub(/.$/,"",$1); print $1", "$NF; f=0} /ANSWER SECTION/{f=1}'
www.google.com, 216.58.193.196
fd-fp3.wg1.b.yahoo.com, 206.190.36.45

Как это устроено

awk неявно читает свои входные данные по одной записи (строке) за раз. Этот скрипт awk использует одну переменную, fкоторая указывает, была ли предыдущая строка заголовком раздела ответа или нет.

  • f{sub(/.$/,"",$1); print $1", "$NF; f=0}

    Если предыдущая строка была заголовком раздела ответа, тогда fбудет true и команды в фигурных скобках будут выполнены. Первый удаляет завершающий период из первого поля. Второе печатает первое поле, затем ,следует последнее поле. Третье утверждение сбрасывается fв ноль (ложь).

    Другими словами, fздесь функционирует как логическое условие. Команды в фигурных скобках выполняются, если не fравен нулю (что в awk означает «true»).

  • /ANSWER SECTION/{f=1}

    Если текущая строка содержит строку ANSWER SECTION, то переменная fустанавливается в 1(true).

    Здесь /ANSWER SECTION/служит логическим условием. Значение true, если текущий соответствует регулярному выражению ANSWER SECTION. Если это так, то команда в фигурных скобках выполняется.


Спасибо @ John1024! Я не знал, что awk не обязательно должен быть в цикле (я думал, что он будет действовать только в последней строке, если он будет снаружи). Является fли произвольная переменная или f{}явной частью функциональности awk?
Линуб

Пожалуйста. fэто произвольная переменная. Вы действительно можете поставить перед {}сложными логическими условиями. fэто просто очень простое логическое условие: оно истинно, если не равно нулю, ложно, если равно нулю.
John1024

@Linoob Обратите внимание, что во второй команде /ANSWER SECTION/играет роль логического условия, аналогичного роли fв первой команде. Я обновил ответ, чтобы обсудить это.
John1024

7

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

Это должно дать вам вывод, который вы хотите:

dig -f hostlist.txt +noall +answer +search | 
    awk '{sub(/\.$/,"",$1); print $1","$5}'

awk«S sub()функция используется для полосы буквального периода .от конца первого поля. Затем awkпечатает поля 1 и 5 через запятую.

ПРИМЕЧАНИЕ: записи, hostlist.txtкоторые не разрешены, полностью удаляются - они не отображаются в stdout ИЛИ stderr.

(Проверено на Linux и FreeBSD)


6

Измените ваш вызов gawkна следующее:

| gawk '{print substr($1,1,length($1)-1)","$NF}' >fqdn-ip.csv
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.