LINUX.ORG.RU

Регулярные выражения

 


0

1

Доброго времени. Для начала подскажите, пожалуйста, как можно более четко выделить участки текста, выделение цветом вообще не нашел, пробовал выделить жирным курсивом, но к сожалению, *** которые указаны в инструкции, дают только *** , а не жирный курсив. ** действительно работают, поэтому выделил пока только ими - но их практически не видно….

Начал изучать регулярные выражения, помогите, пожалуйста, новичку)

Имеем два варианта команды:

echo "Такие вОт раЗНые 245 слова бывают 89 в наШеМ предЛОЖении КРОМЕ" | grep -E "[[:lower:]][[:upper:]]"

Такие вОт раЗНые 245 слова бывают 89 в наШеМ предЛОЖении КРОМЕ

Тут я могу предположить, что мы тут имеем две квадратные скобки, в которых есть либо [:lower:] либо [:upper:], по одному символу в каждой, и выбрать должно неразрывное сочетание «малыйБОЛЬШОЙ» символы

и второй вариант:

echo "Такие вОт раЗНые 245 слова бывают 89 в наШеМ предЛОЖении КРОМЕ" | grep -E "[[:lower:][:upper:]]"

Такие вОт раЗНые 245 слова бывают 89 в наШеМ предЛОЖении КРОМЕ

А вот здесь я вообще не понял, по какому принципу выбрался текст, окрасились все буквы, кроме цифр



Последнее исправление: kimalex (всего исправлений: 4)

окрасились все буквы, кроме цифр

Где окрасилсь? Grep выбирает строку целиком, всю, если в ней есть вхождения, которые соответсвуют шаблону рег. выражения.

dmitry237 ★★★★
()
Ответ на: комментарий от dmitry237

В первом случае grep окрасил карсным цветом по две буквы в каждом слове, одну маленькую, другую большую, они выделены жирным цветом (к сожалению, я не могу сделать это в сообщении) А во втором - окрасил все слова, кроме цифр

kimalex
() автор топика
Ответ на: комментарий от Aceler

В первом примере выбрались только одна большая и одна маленькая буква в каждом слове, где есть такое сочетание. Вот втором - выбрались все буквы во всех словах, кроме цифр

kimalex
() автор топика
Ответ на: комментарий от kimalex

Вот втором - выбрались все буквы во всех словах, кроме цифр

Это потому, что [[:lower:][:upper:]] обработалось, не как два класса [[:lower:]] и [[:upper:]], а как набор символов [символы]

Попробуйте инвертировать и у вас будут только цифры:

echo "Такие вОт раЗНые 245 слова бывают 89 в наШеМ предЛОЖении КРОМЕ" | grep --color -E "[^[:lower:][:upper:]]"
dmitry237 ★★★★
()
Ответ на: комментарий от dmitry237

Спасибо, по немногу начинает доходить. Подскажите, но ведь в приложении есть слова, которые состоят только из маленьких или только больших букв - почему они то же полностью выбрались, в них же нет сочетания «БОЛЬШАЯмаленьшкая»?

kimalex
() автор топика
Ответ на: комментарий от kimalex

Регулярки как написаны так и покрашено. В первой написано «сначала маленькая буква, потом большая». Во второй написано «маленькая или большая буква». Про то что греп ищет все вхождения выше уже писали.

cobold ★★★★★
()
Ответ на: комментарий от dmitry237

Я бы даже быстрее понял, если бы получилось, что я указал классы, и в соответствии с этим выбрались все большие и все маленькие во всех словах. Но как раз в этом случае выбрались только сочетания «БОЛЬШАЯмаленькая» буквы А вот в случае с [[:lower:][:upper:]] выбралось не сочетание «БОЛЬШАЯмаленькая», а вообще все, даже в тех словах, где были только маленькие или только большие буквы….((

kimalex
() автор топика
Ответ на: комментарий от Aceler

У меня выбралась не так, как я себе это представляю: когда указываю как два класса символов [[:lower:]][[:upper:]] - выбрались только отдельные сочетания двух букв только в тех словах, где они одновременно присутствуют, мне казалось, что [[:lower:]] должен был выбрать все маленькие во всех словах, а [[:upper:]] - все большие во всех словах, а вот [[:lower:][:upper:]] - только сочетания букв. А получился прямо противоположный результат

kimalex
() автор топика
Ответ на: комментарий от cobold

Ок, «маленькая или большая» - а выбрал все, и маленькие, и большие. И не по одной, а вообще все. Почему так?

kimalex
() автор топика
Ответ на: комментарий от kimalex

Очевидно, ты в своём предположении неправ. Ты попросил регулярку выбрать все символы, среди которых встречаются или маленькие буквы, или большие. Добавь туда числа [[:lower:][:upper][:number:]], и grep вообще всё выделит, кроме запятых и пробелов.

Если тебе нужны слова только из маленьких букв или только из больших, используй квантификатор на класс, типа [[:lower:]]+.

Aceler ★★★★★
()
Ответ на: комментарий от kimalex

Потому что греп в жадном режиме и после того, как он нашёл что-то, он берёт эту же строку и продолжает искать.

Aceler ★★★★★
()
Ответ на: комментарий от kimalex

Он их и выбрал по одной. Встретил подходящую подстроку (из одной буквы в данном случае) - выделил. Идёт дальше, опять подходящая подстрока (из одной буквы опять же) - и ее выделил. И так далее. Там где пробелы и цифры, там не выделял

cobold ★★★★★
()
Ответ на: комментарий от kimalex

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

  1. [a-z][A-Z] – совпадения только: маленькая и следом большая буквы

  2. [a-zA-Z] – совпадения: любые буквы

[abcdfghjklmnpqrstvwxyz] == [a-z] == [[:lower:]]

[ABCDFGHJKLMNPQRSTVWXYZ] == [A-Z] == [[:upper:]]

TPPPbIHDELj
()
Последнее исправление: TPPPbIHDELj (всего исправлений: 1)

Тебе надо понять из чего может состоять регулярное выражение. Оно не однородно.

В данном случае, у тебя речь идёт об отдельном компоненте регулярных выражений, который состоит из квадратных скобок и «язык» внутри этих скобок отличается от основного языка.

Например, ^ вне скобок означает начало строки, а внутри — инвертирование. Это чтоб ты уловил, что внутри скобок как бы идёт подвид регулярных выражений и заучивать надо отдельно.

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

[] — это диапазоны символов. Каждая такая конструкция подразумевает только один символ из диапазона.

[:upper:] — это символьный класс по стандарту POSIX. В данном случае все буквы верхнего регистра.

[[:upper:]] — это диапазон символов, состоящий из одной любой буквы верхнего регистра.

Теперь помедитируй над разницей между [[:foo:]][[:bar:]] и [[:foo:][:bar:]].

Для наглядности я б посоветовал отложить пока эти классы символов и вернуться к классическим диапазонам, но могут быть косяки, если система имеет локализацию, так как там будет порядок символов не ASCII, а лексикографический.

Чтоб обойти проблему напиши в терминал

export LANG=POSIX

То же самое пиши в скрипты.

Теперь можешь использовать традиционные [A-Z], [a-z], [0-9] и т.д. без проблем.

Рекомендую почитать книгу «Командная строка Linux» Уильяма Шоттса. Книга написана довольно фигово (имхо), но лучше (для новичка) по этой теме ты всё равно ничего не найдёшь.

papin-aziat ★★★★★
()
Ответ на: комментарий от Aceler

Спасибо всем большое за Ваше терпение с такими как я)) Я не самый тупой, но иногда на чем-то простом как заклинит, без чужой помощи не расклиниться))

И вроде понял, почему в голове возникла путаница: запомнилась такая команда:

echo "bbbgbgggbbzip" | grep -E '[bg]zip'

bzip

т.е. из квадратных скобок всегда берется под отдельности, или b или g. И я не понял, что это только в случае сочетания с символами за квадратными скобками скобками, решил, что из них всегда берется один символ из множества, но один раз. Попробовал без них:

echo "bbbgbgggbb" | grep -E '[bg]'

bbbgbgggbb

т.е. выбралась вся строка

Спасибо всем, кто был неравнодушен))

kimalex
() автор топика
Ответ на: комментарий от kimalex

[bg]zip

Вот как это понимает интерпретатор регулярных выражений: обязательно b или g, за которым обязательно следует z, за которым обязательно следует i, за которым обязательно следует p. То есть или bzip, или gzip и на этом всё.

grep -E

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

papin-aziat ★★★★★
()

Тебе все буквы надо выбрать, но не цифры?

echo "Такие вОт раЗНые 245 слова бывают 89 в наШеМ предЛОЖении КРОМЕ" | grep -E "[[:lower:]*[:upper:]]*"
CrX ★★★★★
()
Ответ на: комментарий от CrX

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

kimalex
() автор топика
Ответ на: комментарий от kimalex

Ну без звёздочки оно тебе выбирало две буквы — одна любая маленькая, а за ней любая большая. Звёздочка означает «любое количество» символа перед звёздочкой.

А вообще если задача стоит именно вот «всё кроме цифр и пробела», то лучше так и сказать:

echo "Такие вОт раЗНые 245 слова бывают 89 в наШеМ предЛОЖении КРОМЕ" | grep -E "[^0-9 ]*" 
CrX ★★★★★
()
Последнее исправление: CrX (всего исправлений: 1)
Ответ на: комментарий от papin-aziat

Ну, т.е. если очень грубо говорить на примере [bg]zip, то либо b, либо g по отдельности будут сочетаться с zip. Но если за квадратными скобками (и перед ними, я проверял) ) ничего не стоит, то b и g сочетаться уже (кроме как с сами собой) не с чем, они последовательно выбираются со всей строки. Причем не вперемешку выбираются (из квадратных скобок символы берутся по-отдельности), а вначале допустим все b, потом потом все g, пока все не закончатся. А если брать не [bg], а [b][g] - то это уже два отельных множества, которые последовательно идут друг за другом, и только по одному симовлову, поэтому выберутся не все b и не все g, а только сочетания bg. То же самое получилось с [[:upper:]][[:lower:]], но поскольку они обозначают не отдельные символы, а целые множества только маленьких или только больших букв - они последовательно выделил все, кроме цифр.

Я правильно рассуждаю?

kimalex
() автор топика
Ответ на: комментарий от papin-aziat

Кстати, ещё один момент:

echo «bbbgbgggbb» | grep -E ‘[bg]’

здесь, поскольку за квадратными скобками ничего нет, сочетаться b и g не с чем, и для выбора всех букв достаточно просто [bg], и [bg]* или [bg]+ не требуется?

kimalex
() автор топика
Ответ на: комментарий от kimalex

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

Так у тебя в строке zip один раз, вот и взял :-)

Сделай так: echo "bbbzipgbbbgzipgggbbzip" | grep -E '[bg]zip'

Получишь два раза bzip и один раз gzip

Aceler ★★★★★
()
Ответ на: комментарий от Aceler

Меня в заблуждение ввело ещё и то, что решил, будто в конструкции:

[[:upper:][:lower:]] они находятся внутри общих квадратных скобок, поэтому должны рассматриваться как единое сочетание, и должны выделить только по две буквы (ну или кратные сочетания) по типу «БОЛЬШАЯмаленькая», а вот если они идут по отдельности [[:upper:]][[:lower:]] - то они уже независимо «накрывают» все буквы во всех словах в предложении.

А когда по факту получилось ровно наоборот - стал звать на помощь)))

kimalex
() автор топика
Ответ на: комментарий от Aceler

Абалдеть, какие кардинально разные результаты в

grep -E '[bg]'

и в

grep -E '[b][g]'

kimalex
() автор топика
Ответ на: комментарий от kimalex

Я правильно рассуждаю?

Вроде да, но мы как бы в сферическом вакууме рассуждаем, без конкретики.

[b][g]

Это просто bg, поскольку множества состоят из одного символа.

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

То есть в строке должна быть где-то последовательность bg в любом количестве, иначе мимо.

[bg]

В строке должна быть где-то либо b, либо g в любом количестве, иначе мимо.

[[:upper:][:lower:]]

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

То есть будет выбрана любая строка, в которой есть буквы.

papin-aziat ★★★★★
()
Последнее исправление: papin-aziat (всего исправлений: 1)
Ответ на: комментарий от kimalex

Тут дело в самом grep. Он ищет строки, которые соответствуют шаблону.

В данном случае будут найдены все строки, в которых есть хотя бы один b или g. (программистам такое простое объяснение может не понравиться)

Единственная строка bbbgbgggbb соответствует шаблону [bg].

grep -E

Ключ -E заставляет работать grep в режиме расширенных регулярных выражений. В данных случаях этого не требуется, поскольку никаких возможностей не используется.

Я советую разобраться в чём разница между BRE и ERE, так как в разных случаях будет удобнее разное, и разные программы используют разный диалект.

papin-aziat ★★★★★
()
Последнее исправление: papin-aziat (всего исправлений: 1)

Они так не работают. Для изменения регистра есть другие утилиты:

> tr '[:upper:]' '[:lower:]' <<< "This SHIT"                                                     
this shit

Для юникод:

perl -CSD -pe 'use utf8; $_ = lc($_)' <<< "Такие вОт раЗНые 245 слова бывают 89 в наШеМ предЛОЖении КРОМЕ"
такие вот разные 245 слова бывают 89 в нашем предложении кроме

Я туплю:

grep -oE '[[:upper:]][[:lower:]]' <<< "Такие вОт раЗНые 245 слова бывают 89 в наШеМ предЛОЖении КРОМЕ" | tr -d '\n'
ТаОтНыШеЖе
rtxtxtrx ★★
()
Последнее исправление: rtxtxtrx (всего исправлений: 1)
Ответ на: комментарий от kimalex

То же самое получилось с [[:upper:]][[:lower:]], но поскольку они обозначают не отдельные символы, а целые множества только маленьких или только больших букв - они последовательно выделил все, кроме цифр.

Не всё, кроме цифр, а только сочетания, где сначала идёт буква в верхнем, а за ней в нижнем.

То есть строка без такого сочетания будет пропущена.

papin-aziat ★★★★★
()
Последнее исправление: papin-aziat (всего исправлений: 1)
Ответ на: комментарий от papin-aziat

Внутри не нужно на самом деле. Это я что-то перемудрил

CrX ★★★★★
()
Для того чтобы оставить комментарий войдите или зарегистрируйтесь.