Вопрос или проблема
Что не так с этим скриптом 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
.
Рекомендации по исправлению:
-
Используйте кавычки:
Оберните переменную в кавычки, чтобы сохранить построчные разделения:
acme3=$(echo "$acme2" | grep "^_acme")
-
Использование
printf
:Более надёжным способом будет использование
printf
:acme3=$(printf '%s\n' "$acme2" | grep "^_acme")
Это позволяет сохранить форматирование вывода.
-
Упрощенное использование
dig
:Прямо используйте
dig
, чтобы получить только заинтересованный результат:acme3=$(dig +short txt @"$1" "_acme-challenge.$1.de")
Здесь флаг
+short
директно вызывает только интересующую информацию без излишней передачи данных.
Заключение
Практика правильного управления строками в Bash имеет важное значение в лозунге исправления и отладки скриптов. Основным уроком здесь является использование кавычек для сохранения целостности данных, передаваемых через переменные. Это важно не только для успешной работы grep
, но и для других инструментов UNIX, которые могут использовать форматированные данные.
На основе рассмотренного выше материала, любой, кто сталкивается с подобной проблемой, может более осознанно подходить к обработке консольных команд и избежать аналогичных досадных ситуаций, что в конечном итоге приводит к более действенному программированию в среде UNIX/Linux.