У меня есть регулярное выражение:
\b[-+]?(?:\d{1,3}\.)(?:\d{3}\.)*(?:\d*)
(Python), который соответствует числовым значениям в таких строках:
Amount: 12.234.55222 EUR
Some Text 123.222.22 maybe more text
1.245.455.2
22.34565 Could be at the beginning
It could be at the end of a string 21.1
221. It could be a number like this too (for US invoices, I saw a lot of different stuff)
Это то, чего я хочу.
Но оно также соответствует первым двум частям даты, например: 08.05.2023
Я знаю, что это происходит из-за первой и последней группы, но не знаю, как это предотвратить.
Я хочу соответствовать только тем ценностям, которые стоят сами по себе.
Может ли кто-нибудь указать мне правильное направление?
Редактировать: Забыл упомянуть, что пробовал с негативным взглядом сзади, но не сработало:
\b([-+]?(?:\d{1,3}\.)(?:\d{3}\.)*(?:\d*))(?!(?:\.d{4}))
Может я неправильно смотрю сзади?
Это отличная идея, мне она нравится. Большое спасибо, я предоставлю код, когда закончу.
Ваши требования не очевидны из примеров, которые вы хотите сопоставить, и из одной строки, которую вы не хотите сопоставлять. Если вы точно укажете словами характеристики строк, которые вы хотите сопоставить с требуемым регулярным выражением, скорее всего, сразу выпадут. Обязательно укажите, хотите ли вы сопоставить всю строку или часть строки, если соблюдены определенные требования. Например, может ли строка быть "The string 12.234.55222 is an unusual phone number"
, а не просто "12.234.5522"
.
@CarySwoveland Я хочу сопоставить все возможные строки, связанные с деньгами. Но я хочу предотвратить положительные падения, которые могут произойти, если мое регулярное выражение также соответствует такой дате. Я опубликовал решение своей проблемы с помощью пользователя 24714692.
Обратите внимание, что (?!(?:\.d{4}))
, который является отрицательным опережением, можно упростить до (?!\.d{4})
. Также «...но это не сработало...» расплывчато. Неясно, было ли регулярное выражение Python недействительным или оно не соответствовало строке, которая должна была сопоставляться, или соответствовало строке, которая не должна сопоставляться. Стремитесь быть точными во всем, что касается кодирования.
С идеей @user24714692 я сделал это следующим образом:
def float_check(text: str) -> bool:
try:
float(text)
return True
except ValueError:
return False
def match_amount(amount: float, text: str) -> bool:
pattern = r"^([-+]?(?:\d{1,3}\.)(?:\d{3}\.)*(?:\d*))$"
# find all numbers, that match a pattern like i.e.: (123./,)*23
# replace all comma, because the US is doing the numbers like this 291,234.23
text = text.replace(",", ".")
numbers = [
pot_number for pot_number in text.split() if re.findall(pattern, pot_number)
]
for number in numbers:
# now replace all dots but the last one
number = re.sub(r"\.(?=.*\.)", "", number)
# and convert the numbers to float, and check if the number equals the given amount
if float_check(number) and float(number) == amount:
return True
return False
print(match_amount(23.45, "some text with numbers here"))
Сейчас работает нормально, большое спасибо.
Я предположил, что строки должны соответствовать одному из форматов, заданных в шести примерах. Например, я предположил, что "12.234.55222"
представляет строки, состоящие из двух цифр, за которыми следует точка, за которой следуют три цифры, за которыми следует точка, за которой следуют пять цифр.
Вы можете сопоставить регулярное выражение
^[+-]?(?:\d\.\d{3}\.\d{3}\.\d|\d{2}\.(?:\d{3}\.\d{5}|\d{6}\.\d|\d{2}\.\d)|\d{3}\.(?:\d{3}\.\d{2})?)$
Я написал выражение по ссылке в расширенном режиме или режиме со свободным интервалом, чтобы его было легче читать и чтобы оно было самодокументируемым.
Если примеры могут быть частями строк (а не всей строкой), замените ^
двумя отрицательными просмотрами назад, (?<!.)(?<!\d)
, и замените $
отрицательным просмотром вперед, (?![.\d])
.
Ах, извините, мне нужно немного уточнить вопрос. Строки не обязательно должны находиться в конце/начале строки. Может быть что-то вроде этого: Сумма: 123.222,22 евро. Но для случая, который я представил, он работает нормально. Обновлено: теперь вопрос более ясен, все равно спасибо за помощь.
Последнее предложение моего ответа объясняет, как следует изменить предложенное мной регулярное выражение, чтобы ответить на ваш вопрос в его нынешнем виде, после вашего редактирования. Вы можете убедиться в этом, изменив регулярное выражение и тестовые строки по ссылке «Демо», которую я дал.
Разделите на места и пользуйтесь
^([-+]?(?:\d{1,3}\.)(?:\d{3}\.)*(?:\d*))$
? В противном случае, если у вас длинная строка, это станет слишком дорого. Это денежные ценности12.234.55222
или221.
?