Почему оператор bash «=~» игнорирует последнюю часть указанного шаблона?

Я пытаюсь сравнить строку в 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 делать это?

Инструменты для веб-скрапинга с открытым исходным кодом: Python Developer Toolkit
Инструменты для веб-скрапинга с открытым исходным кодом: Python Developer Toolkit
Веб-скрейпинг, как мы все знаем, это дисциплина, которая развивается с течением времени. Появляются все более сложные средства борьбы с ботами, а...
Калькулятор CGPA 12 для семестра
Калькулятор CGPA 12 для семестра
Чтобы запустить этот код и рассчитать CGPA, необходимо сохранить код как HTML-файл, а затем открыть его в веб-браузере. Для этого выполните следующие...
ONLBest Online HTML CSS JAVASCRIPT Training In INDIA 2023
ONLBest Online HTML CSS JAVASCRIPT Training In INDIA 2023
О тренинге HTML JavaScript :HTML (язык гипертекстовой разметки) и CSS (каскадные таблицы стилей) - две основные технологии для создания веб-страниц....
Как собрать/развернуть часть вашего приложения Angular
Как собрать/развернуть часть вашего приложения Angular
Вам когда-нибудь требовалось собрать/развернуть только часть вашего приложения Angular или, возможно, скрыть некоторые маршруты в определенных средах?
Запуск PHP на IIS без использования программы установки веб-платформы
Запуск PHP на IIS без использования программы установки веб-платформы
Установщик веб-платформы, предлагаемый компанией Microsoft, перестанет работать 31 декабря 2022 года. Его закрытие привело к тому, что мы не можем...
Оптимизация React Context шаг за шагом в 4 примерах
Оптимизация React Context шаг за шагом в 4 примерах
При использовании компонентов React в сочетании с Context вы можете оптимизировать рендеринг, обернув ваш компонент React в React.memo сразу после...
4
0
54
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Вы смешиваете синтаксис шаблонов оболочки и регулярных выражений. Ваше регулярное выражение, после удаления кавычек, будет John*: Joh, за которым следует любое количество n, включая 0. Соответствует Joh, John, Johnn, Johnnn,...

Он не привязан, поэтому он также соответствует любой строке, содержащей одно из приведенных выше совпадений.

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

  • Любая строка, содержащая John, должна соответствовать:
    • Регулярное выражение: [[ $name =~ John ]]
    • Выкройка ракушки: [[ $name == *John* ]]
  • Любая строка, начинающаяся с John, должна соответствовать:
    • Регулярное выражение: [[ $name =~ ^John ]]
    • Выкройка ракушки: [[ $name == John* ]]

Обратите внимание, что шаблоны оболочки, в отличие от регулярных выражений, должны соответствовать всей строке.

Примечание по поводу цитирования: внутри [[ ... ]] левую часть не нужно заключать в кавычки; в правой части кавычки интерпретируются буквально. Для регулярных выражений рекомендуется определять его в отдельной переменной:

re='^John'
if [[ $name =~ $re ]]; then

Это позволяет избежать нескольких пограничных случаев со специальными символами в регулярном выражении.

Ах это имеет смысл. Я, очевидно, изменил то, над чем я работаю, для простого примера, но проблема, над которой я пытаюсь работать, заключается в поиске строки, которая должна начинаться с некоторых определенных символов, а затем может иметь что угодно после нее. Решение с использованием ^ было именно тем, что мне было нужно. Спасибо

Tyler 14.02.2023 17:42

Оператор =~ сравнивает с использованием синтаксиса регулярного выражения, а не синтаксиса glob. * не является подстановочным знаком оболочки, это означает «предыдущий символ, 0 или более раз».

Строка Joh соответствует регулярному выражению John*, поскольку содержит Joh, за которым следуют нулевые n символы.

Соскучилась по нему сильно... :)

larsks 14.02.2023 17:31

Что касается моего редактирования, я бы поостерегся называть его регулярным выражением, поскольку «сопоставление с образцом» — это имя операции, которая сопоставляется с глобусами, поэтому полезно зарезервировать слово «шаблон» для чего-то, что использует синтаксис глобуса.

chepner 14.02.2023 17:33

Другие вопросы по теме

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

Разобрать отформатированную строку с метками, написанными ЗАГЛАВНЫМИ БУКВАМИ, за которыми следует их значение, для создания ассоциативного массива.
Разделить строку с помощью разделителей и поместить их в несколько строк в sql, не работающем
Регулярное выражение с флагом m в Perl и Python
Как выполнить разделение строк, используя регулярное выражение в качестве ссылки, и чтобы часть используемого шаблона разделителя не удалялась из следующей строки?
Правильный шаблон регулярного выражения (re) в python
Как я могу преобразовать двойные косые черты в R, не сталкиваясь с ошибкой, связанной с escape-символами?
JavaScript Буквенно-цифровое регулярное выражение и разрешить звездочку в начале строки, но не разрешать звездочку в последних 4 цифрах строки
Python/regex: соответствует только букве или букве, за которой следует число
Регулярное выражение для форматирования электронной почты без hypen в начале и в конце
Как написать регулярное выражение, которое удаляет любой символ или символ, стоящий перед диапазоном указанных разделителей "(" и ")]"