установить вывод в переменную из grep из входной переменной

Вопрос или проблема

Что не так с этим скриптом bash:

acme2=$(dig txt @$1 _acme-challenge.$1.de)                                            
acme3=$(echo $acme2 | grep "^_acme")                                                    

acme2 содержит весь вывод, но
acme3 всегда пуст

Я искал несколько решений и пробовал другие возможности, но ничего не работает…

acme3=echo $acme2|grep acme                                                          
acme3=$($acme2|grep "^_acme")                                                        
acme3=$(grep "acme" $acme2)                                                          
acme3=$(echo "$acme2" | grep "^_acme")                                              

Мы действительно не можем помочь, так как не имеем представления, что содержится в $acme2, но я могу сказать вам, что ваша команда grep ищет строки, которые начинаются с _acme. Поскольку вывод команды dig состоит из нескольких строк и вы выводите переменную без кавычек, все будет на одной строке, поэтому, если только первая строка вывода не _acme, ваша команда grep ничего не найдет. Чтобы продемонстрировать:

$ seq 3
1
2
3

$ acme=$(seq 3)

$ echo $acme
1 2 3

$ echo "$acme"
1
2
3

$ echo $acme | grep '^2'
$

$ echo "$acme" | grep '^2'
2

Поэтому, если у вас есть хотя бы одна строка в вашем выводе dig, которая начинается с _acme, правильное использование кавычек в вашей переменной (что вы всегда должны делать, кстати) должно сработать:

acme3=$(echo "$acme2" | grep "^_acme")

Или лучше, особенно для таких произвольных данных:

acme3=$(printf '%s\n' "$acme2" | grep "^_acme")                 

Обе строки можно объединить, сообщив dig, что вас интересует только его прямой вывод:

#!/bin/sh
acme3=$(dig +short txt @"$1" "_acme-challenge.$1.de")

Это также обходит проблему с echo $acme2, который почти наверняка должен был быть echo "$acme2" или даже printf '%s\n' "$acme2". (Опускание двойных кавычек приводит к тому, что содержимое переменной $acme2 обрабатывается как токены, разделенные пробелами, что приводит к тому, что весь вывод оказывается на одной строке.)

Ответ или решение

В описанном сценарии идет речь об обработке данных в Bash, что может стать настоящей головоломкой для начинающих. Проблема имеет отношение к тому, как Bash работает с переменными и обработкой строк. Позвольте мне разобрать детали и предложить обоснованное решение.

Теория

Когда вы работаете с командной строкой Bash, правильное обращение с переменными и выводом команд особенно важно. Каждая команда или программа генерирует выходные данные, которые при необходимости могут быть занесены в переменную для дальнейшей обработки. Важно учитывать, что Bash интерпретирует знаки начала строки (^) и другие шаблоны в grep как условие поиска строки, которое работает именно на построчном уровне. Потому, когда все выводы помещаются в одну строку (например, когда отсутствует корректное заключение в кавычки), grep не сможет идентифицировать начало новой строки и не выполнит ожидаемое действие.

Пример

Рассмотрим приведенный пример:

acme2=$(dig txt @$1 _acme-challenge.$1.de)
acme3=$(echo $acme2 | grep "^_acme")

Здесь acme2 получает вывод из команды dig, которая в свою очередь выполняет DNS-запрос. Далее, переменная acme3 должна была бы содержать строки, начинающиеся с _acme, но команда echo $acme2 формирует все данные в одну строку, из-за чего grep "^_acme" не может обнаружить начало строки.

Применение

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

Рекомендации по исправлению:

  1. Используйте кавычки:

    Оберните переменную в кавычки, чтобы сохранить построчные разделения:

    acme3=$(echo "$acme2" | grep "^_acme")
  2. Использование printf:

    Более надёжным способом будет использование printf:

    acme3=$(printf '%s\n' "$acme2" | grep "^_acme")

    Это позволяет сохранить форматирование вывода.

  3. Упрощенное использование dig:

    Прямо используйте dig, чтобы получить только заинтересованный результат:

    acme3=$(dig +short txt @"$1" "_acme-challenge.$1.de")

    Здесь флаг +short директно вызывает только интересующую информацию без излишней передачи данных.

Заключение

Практика правильного управления строками в Bash имеет важное значение в лозунге исправления и отладки скриптов. Основным уроком здесь является использование кавычек для сохранения целостности данных, передаваемых через переменные. Это важно не только для успешной работы grep, но и для других инструментов UNIX, которые могут использовать форматированные данные.

На основе рассмотренного выше материала, любой, кто сталкивается с подобной проблемой, может более осознанно подходить к обработке консольных команд и избежать аналогичных досадных ситуаций, что в конечном итоге приводит к более действенному программированию в среде UNIX/Linux.

Оцените материал
Добавить комментарий

Капча загружается...