Я пытаюсь сравнить строку в bash с шаблоном регулярного выражения и нашел что-то странное. Для начала я использую GNU bash версии 5.0.17(1)-релиз (x86_64-pc-linux-gnu). Это внутри WSL.
Например, вот пример программы, демонстрирующий проблему:
#!/bin/env bash
name = "John"
if [[ "${name}" =~ "John"* ]]; then
echo "found"
else
echo "not found"
fi
exit
Как и ожидалось, это будет эхом found, поскольку имя «Джон» соответствует описанному шаблону регулярного выражения. Что мне кажется странным, так это то, что если я уберу букву n в имени John, она все равно будет повторяться found. Imo "Joh" соответствует образцу "John"*.
Если вы отбросите «hn» и просто установите для $name значение «Jo», тогда будет эхо not found. Кажется, это влияет только на последний символ в шаблоне Regex (кроме подстановочного знака).
Я конвертирую старый скрипт csh в bash, и в csh такого не происходит. Что заставляет bash делать это?
Вы смешиваете синтаксис шаблонов оболочки и регулярных выражений. Ваше регулярное выражение, после удаления кавычек, будет John*: Joh, за которым следует любое количество n, включая 0. Соответствует Joh, John, Johnn, Johnnn,...
Он не привязан, поэтому он также соответствует любой строке, содержащей одно из приведенных выше совпадений.
Поскольку он не привязан, в зависимости от того, что вы хотите, вы можете сделать любой из них:
John
, должна соответствовать:
[[ $name =~ John ]]
[[ $name == *John* ]]
John
, должна соответствовать:
[[ $name =~ ^John ]]
[[ $name == John* ]]
Обратите внимание, что шаблоны оболочки, в отличие от регулярных выражений, должны соответствовать всей строке.
Примечание по поводу цитирования: внутри [[ ... ]] левую часть не нужно заключать в кавычки; в правой части кавычки интерпретируются буквально. Для регулярных выражений рекомендуется определять его в отдельной переменной:
re='^John'
if [[ $name =~ $re ]]; then
Это позволяет избежать нескольких пограничных случаев со специальными символами в регулярном выражении.
Оператор =~ сравнивает с использованием синтаксиса регулярного выражения, а не синтаксиса glob. * не является подстановочным знаком оболочки, это означает «предыдущий символ, 0 или более раз».
Строка Joh соответствует регулярному выражению John*, поскольку содержит Joh, за которым следуют нулевые n символы.
Соскучилась по нему сильно... :)
Что касается моего редактирования, я бы поостерегся называть его регулярным выражением, поскольку «сопоставление с образцом» — это имя операции, которая сопоставляется с глобусами, поэтому полезно зарезервировать слово «шаблон» для чего-то, что использует синтаксис глобуса.
Ах это имеет смысл. Я, очевидно, изменил то, над чем я работаю, для простого примера, но проблема, над которой я пытаюсь работать, заключается в поиске строки, которая должна начинаться с некоторых определенных символов, а затем может иметь что угодно после нее. Решение с использованием ^ было именно тем, что мне было нужно. Спасибо