Вопрос:
Может кто-нибудь, пожалуйста, дайте мне знать, что Regex используется для нахождения чисел, которые имеют кратность 4 из заданной строки. Строка будет состоять как из текста, так и из цифр.
заранее спасибо
Лучший ответ:
С регулярным выражением вы можете извлекать только целые числа. Однако можно извлечь только четные числа:
(d*[02468])
Затем вы должны проверить их, если они делятся на 4 с модульным тестом:
if ( ( number != 0 ) && ( number % 4 == 0 ) ) { // number is dividable with 4 and does not equal 0 } Ответ №1
жалуясь, что регулярное выражение не является правильным инструментом для работы, на самом деле не отвечает на этот вопрос, и я думаю, что это какой-то контрпродуктив. Хотя может быть и правдой, что аскер просто не знает, что есть лучший способ. Однако, может быть, он строит лексер для совершенно нового компилятора языка, который принимает только определенные делители в качестве токенов?
Это может быть маловероятным и нецелесообразным, но я хочу сказать, что вынесение суждения о предполагаемом мотиве никого не значит… ANYWAY…
Я думаю, что это интересный вопрос, если по какой-либо другой причине, чем он представляет интересную задачу в академическом плане, и чтобы ответить на ваш вопрос, есть способ использовать регулярное выражение для определения кратных значений.
В конечном счете регулярное выражение – это просто шаблонный шаблон? поэтому какие типы шаблонов могут быть созданы числами в четыре раза? Чтобы ответить на этот вопрос, я написал краткую программу для распечатки всех кратных четырех из 1 – 500 (попробуйте);
import java.io.FileWriter; public class Four { public static void main(String args[]){ StringBuilder myFour = new StringBuilder(); int i = 1; int mult = 0; while(mult < 500){ mult = i*4; myFour.append(mult + «|»); i++; } try{ FileWriter writer = new FileWriter(«out.txt»); writer.write(myFour.toString()); writer.close(); } catch(Exception e){e.printStackTrace();} } }
я заметил, что последняя цифра каждого номера чередовалась между 0 4 8 2 6. Теперь у вас может возникнуть соблазн использовать это немедленно и просто проверить все строки цифр, чтобы увидеть, заканчиваются ли они одним из этих чисел, но это не будет работа, так как другие целые числа также заканчиваются теми цифрами, которые сами по себе не делятся на четыре таких, как 10, 14, 18, 22, 26 и т.д…. и поэтому поиск продолжается. Затем я просмотрел последние две цифры и заметил повторяющийся шаблон между 0 и 100
4 | 8 | 12 | 16 | 20 | 24 | 28 | 32 | 36 | 40 | 44 | 48 | 52 | 56 | 60 | 64 | 68 | 72 | 76 | 80 | 84 | 88 | 92 | 96 | 100 |… | 204 | 208 | 212 |…
если вы префикс одиночных цифр с нулями, вы заметите, что этот шаблон повторяется каждый шаг в 100. Так что теперь я чувствую себя довольно уверенно, что я на что-то. Чтобы еще раз проверить мою теорию, я поднял Google и набрал 2147483648% 4 (что является следующим самым большим числом за максимальным 32-битным знаковым значением int, которое делится на 4). Это было только первое произвольное значение, которое приходило в голову и не имело другое значение, о котором я знаю, и, как выясняется, 2147483648% 4 = 0, поэтому я чувствую себя действительно хорошо сейчас. Я полагаю, вы могли бы написать математическое доказательство и доказать, что эта теория работает, но я больше в приложении. Поэтому я считаю, что в этот момент все, что мне нужно сделать, это написать это регулярное выражение, а затем я смогу проверить его на выходе программы, написанной выше. Итак, моя следующая цель – написать реальное регулярное выражение.
Если вы заметили, что я удобно сделал программу распечатать оператор OR регулярного выражения, чтобы я мог просто вырезать и вставить большую часть регулярного выражения, и я на полпути домой. Все, что я хочу, это последние две цифры, поэтому первая часть моего регулярного выражения выглядит примерно так:
(00|04|08|12|16|20|24|28|32|36|40|44|48|52|56|60|64|68|72|76|80|84|88|92|96)
вы заметите, что я префикс нулей на отдельные цифры и добавил 00 на фронт. Опять же, это потому, что я хочу сопоставить последние два символа, включая 00 из 100 (это также вернет строки 0 как действительные кратные четыре, как это должно быть). поэтому теперь у меня есть суффикс регулярного выражения wrtten. Согласно моей теории, любая строка цифр, помеченных вышеупомянутыми двумя цифрами, кратно четырем, поэтому мне просто нужно написать правило для префикса (любая цифра), и я закончил. Это очень просто и просто [0-9] * Итак, теперь мое регулярное выражение выглядит так:
[0-9]*(00|04|08|12|16|20|24|28|32|36|40|44|48|52|56|60|64|68|72|76|80|84|88|92|96)
Теперь я почти закончил. Что я забыл? Одиночные цифры !!! 0,4 и 8 будут отклонены регулярным выражением выше, поскольку они являются одиночными цифрами, и приведенный выше шаблон соответствует только двум цифрам, которым предшествуют 0 или более цифр. поэтому я должен немного настроить регулярное выражение, и в итоге я получаю следующее:
(0|4|8)|([0-9]*(00|04|08|12|16|20|24|28|32|36|40|44|48|52|56|60|64|68|72|76|80|84|88|92|96))
и это в значительной степени. Технически вам также придется добавлять границы слов, так как вы хотите обрабатывать всю строку цифр в виде слова. вы бы добавили граничные теги:
b(0|4|8)|([0-9]*(00|04|08|12|16|20|24|28|32|36|40|44|48|52|56|60|64|68|72|76|80|84|88|92|96))b
но независимо от того, выполняете ли вы это, зависит от вашего приложения. Если вы собираетесь использовать это в лексере, вы можете создать jflex, например, вы, возможно, не захотите включать их, поскольку у вас могут быть другие правила для похожих лексем.
Так что все, что я сделал бы это. Это, вероятно, не кратчайшее кратчайшее регулярное выражение, и я уверен, что есть лучшие способы сделать это, но если вы ищете что-то быстрое и грязное, я не думаю, что он становится быстрее или грязнее. Кроме того, я думал, что это поможет, если я проведу вас через мой мыслительный процесс. Нижняя сторона быстрого и грязного заключается в том, что я могу быть совершенно неправильным, и если так, теперь вы можете видеть, где именно я был снесен с рельсов, и вы можете поставить поезд обратно на треки самостоятельно;) Надеюсь, это поможет…
Ответ №2
Regex – не лучший инструмент для выполнения этой работы, но если вы действительно этого хотите, попробуйте:
/[[0268][048]|[13579][26])(D|$)/