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

Это похоже на zsh-history-substring-search , который, согласно веб-странице, вдохновлен рыбой ] shell (и навскидку похоже на то, как vi-like-emacs реализует историю команд - вероятно, есть несколько вариантов).

Чтобы узнать о других возможностях, см. Ответ @ jasonwryan в Как я могу искать в истории то, что уже введено в командной строке в zsh?

12
26.05.2016, 02:19
3 ответа

Команда 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 будет истиной и будут выполнены команды в фигурных скобках. Первая из них удаляет точку из первого поля. Вторая печатает первое поле, затем ,, затем последнее поле. Третий оператор сбрасывает f в ноль (false).

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

  • / ОТВЕТ НА РАЗДЕЛ/{f=1}

    Если текущая строка содержит строку ОТВЕТ НА РАЗДЕЛ, то переменная f устанавливается в 1 (true).

    Здесь /ПРИМЕРНЫЙ РАЗДЕЛ/ служит логическим условием. Оно оценивается в true, если текущий соответствует регулярному выражению ОТВЕТНЫЙ РАЗДЕЛ. Если совпадает, то выполняется команда в фигурных скобках.

18
27.01.2020, 19:54

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

Это должно дать вам желаемый результат:

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

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

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

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

7
27.01.2020, 19:54

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

| gawk '{print substr($1,1,length($1)-1)","$NF}' >fqdn-ip.csv
6
27.01.2020, 19:54

Теги

Похожие вопросы