Тут є дві проблеми: як @AFH вказував, \s
це стенограма Perl, а не частина стандартного синтаксису POSIX. Стандартний спосіб представити це з класом символів [[:space:]]
. Друга проблема полягає в тому, що змінні посилання не розширюються всередині одиничних лапок; вам потрібно використовувати подвійні лапки (і уникати тієї $
частини регулярного вираження).
Крім того, декілька стилістичних рекомендацій: $( )
як правило, перевагу над задніми посиланнями для заміни команд (це легше читати, і не має деяких дивних незвичних синтаксичних дивацтв, які мають backticks). Але в цьому випадку ви можете пропустити розширення команди; замість того, щоб використовувати wc -l
і порівнювати з нулем, щоб побачити, чи були відповідність, просто використовуйте grep
статус виходу в якості тесту (і -q
можливість уберегти його від друку відповідності). Також не забудьте подвоїти посилання на змінні (наприклад, у echo
команді).
Ось мій рекомендований перепис:
if dpkg -l | grep -Eq "(^|[[:space:]])$i(\$|[[:space:]])"; then echo "$i"; fi
EDIT: як зазначав igor у коментарі, це не працюватиме з іменами пакетів, які містять метасимволи regex (наприклад, g ++ - 5). Можна заздалегідь обробити ім'я пакета, щоб уникнути метахарактерів, але це досить брудно. Але є більш простий спосіб: якщо ви використовуєте bash (а не якусь іншу оболонку), ви можете скористатись базовою функцією rehex bash, щоб виконати відповідність безпосередньо:
if [[ "$(dpkg -l)" =~ (^|[[:space:]])"$i"(\$|[[:space:]]) ]]; then echo "$i"; fi
Причина цього працює в тому, що $i
в середині шаблону є подвійні лапки, що вказує bash відповідати йому як буквальному рядку (тобто ігнорувати будь-які метагерактеристики регулярних виразів у ньому).
g++-5
абоg++-4.9
. Якісь ідеї?