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

Удаленная команда PuTTY, содержащая цикл while
Как проверить подключение к локальной сети с помощью терминала mac os?
Загрузка нескольких файлов с ftp-сервера с помощью сценария bash
Копировать всех пользователей.история bash на одном дыхании
IPTables - разрешить (принять) определенные IP-адреса в заблокированной подсети
Терминал Linux-замороженное обновление ввода, но может выполнять команды?
Что такое SHELL-формат в envsubst?
терминал iTerm/OSX: изменение поля текста от края окна
Bash-скрипт не выполняется при вводе команды в переменную
"/usr/bin / env bash" не найден при запуске из сценария cron
Запуск скрипта bash даже после закрытия терминала
В чем разница между "Shell" и "Terminal"? [дубликат]
Как добавить пункты меню в меню Gnome "приложения" из командной строки?
Нашел скрипт на моем кроне.ежемесячно, мне интересно, что он делает?
grep: выводить конкретную строку после матча

Экранирование символов для точного условия grep в сценарии Bash

у меня есть базовый скрипт для поиска конкретных установленных пакетов в Linux. Если не найден -> распечатать пакет.

Я grep -w, но он не работает должным образом с - символ.

например,

dpkg -l | grep -w "rpm"

также найдете rpm-common.

я нашел решение для этого с помощью regex. Проблема это не работает в bash-скрипт.

устранение:

dpkg -l | grep -E '(^|s)string($|s)'

состояние:

if [ `dpkg -l | grep -E '(^|s)$i($|s)' | wc -l` = 0 ]; then echo$i; fi

$i ссылается на значение массива, например arr[index]=$i.

какие экранирующие символы мне нужно использовать, чтобы условие работало?

5
задан Peter Mortensen
источник

2 ответов

здесь есть две проблемы: как указал @AFH,\s является сокращением Perl, а не частью стандартного синтаксиса POSIX. Стандартный способ представить это-класс символов [[:space:]]. Вторая проблема заключается в том, что ссылки на переменные не раскрываются внутри одинарных кавычек; вам нужно использовать двойные кавычки (и экранировать $ это часть регулярного выражения).

кроме того, несколько стилистических рекомендаций: $( ) обычно предпочтительнее, чем backticks для команды substitution (его легче читать и у него нет некоторых странных странностей синтаксиса, которые есть у обратных ссылок). Но в этом случае можно пропустить расширение команды; вместо использования wc -l и по сравнению с нулем, чтобы увидеть, если были какие-либо матчи, просто используйте grepс выездом статус теста (и -q опция, чтобы держать его от печати матча). Кроме того, убедитесь, что ссылки на переменные заключены в двойные кавычки (например, в echo command).

вот мои рекомендации перепишите:

if dpkg -l | grep -Eq "(^|[[:space:]])$i($|[[:space:]])"; then echo "$i"; fi

EDIT: как отметил Игорь в комментарии, это не будет работать с именами пакетов, которые содержат метасимволы регулярных выражений (например, g++-5). Можно предварительно обработать имя пакета, чтобы избежать метасимволов, но это довольно грязно. Но есть более простой способ: если вы используете bash (а не какую-то другую оболочку), вы можете использовать родную возможность регулярного выражения bash для прямого сопоставления:

if [[ "$(dpkg -l)" =~ (^|[[:space:]])"$i"($|[[:space:]]) ]]; then echo "$i"; fi

причина, по которой это работает, заключается в том, что $i в середине шаблон находится в двойных кавычках, что говорит bash, чтобы соответствовать ему как литеральной строке (т. е. игнорировать любые метасимволы регулярных выражений в нем).

1
отвечен Gordon Davisson 2017-11-19 06:54:57
источник

расширенные регулярные выражения не поддерживают \s, но Perl REs делает, поэтому попробуйте использовать -P вместо -E:

dpkg -l | grep -P '(^|\s)rpm($|\s)'

See этой ссылке для получения дополнительной информации.

на grep инструкции сказано, что -P экспериментальная, но это работает для меня на Ubuntu 16.04.

1
отвечен AFH 2017-11-16 15:10:13
источник

Другие вопросы bash grep linux regex