Регулярное выражение здесь не лучший выбор.
Чтобы проиллюстрировать это, я буду использовать регулярное выражение, которое вы разместили для дела за 1 миллион долларов. Мне кажется, что вы пытаетесь приспособиться к различным условиям, включая такие, как:
$10 vs. $10.00
$100 vs. 100
$100 vs. $10000
$10,000 vs. $100,000
etc.
Но то, как вы это делаете, позволяет такие вещи:
$10000000.00
потому что:
$ matches ^\$?
100 matches \d{0,3}?
00 matches \d{0,2}
[no comma ] matches ,?
000 matches \d{0,3}
.00 matches (\.(\d{0,2}))?$
(проверено с https://regex101.com/)
Иными словами, ваша попытка сопоставить такие вещи, как отсутствие запятой для небольших чисел и наличие запятой для больших чисел, а также различные группировки цифр, которые могут встречаться в маленьких, средних и больших числах, приводит к регулярному выражению это соответствует числу, намного превышающему 1 миллион долларов.
Хотя регулярные выражения достаточно универсальны и современные движки регулярных выражений довольно мощные, надежное регулярное выражение для выполнения того, что вы пытаетесь сделать, было бы громоздким, трудным для чтения и сложным в обслуживании.
Это также было бы достаточно сложно, чтобы показать, каким образом регулярное выражение можно правильно считать языком программирования.
Но, прежде всего, любое регулярное выражение используется в контексте окружающего языка программирования, так почему бы просто не использовать возможности самого языка программирования? Это может занять больше времени, но, вероятно, меньше времени, и результаты будут гораздо проще составлять, читать и поддерживать.