Multiple things are wrong in your expression :
^\{USD}?(\d*(\d\.?|\.\d{1,2}))$
\{USD}? in regex language this would mean: expect the { literal character followed by USD followed by the character } if any. If you want to have an optional group USD you have to use parenthesis without \: (USD)?. You can use a non-capturing group for this : (?:USD)?.
This would give : ^(USD)?(\d*(\d\.?|\.\d{1,2}))$
(\d\.?|\.\d{1,2}), the whole group should be repeated in order to match the entire string : (\d\.?|\.\d{1,2})*
This would give : ^(USD)?(\d*(\d\.?|\.\d{1,2})*)$
\d\.?: if this is supposed to match the part with a thousand separator it should be a comma not a point regarding your example: \d*,?
This would give : ^(USD)?(\d*(\d,?|\.\d{1,2})*)$
(\d*(\d: this won't work, the second \d will never match because all digit will be consumed by the first \d*, you could use the non-greedy operator ? like this: (\d*?(\d but it's not pretty.
This would give : ^(USD)?(\d*?(\d,?|\.\d{1,2})*)$ which may work for you, but looks less than optimal.
An alternative would be to build your regular expression without an "or" clause using the following parts :
- The prefix : "USD ", optional and with optional space :
(USD ?)?
- The integral part of the amount before the thousand separators:
\d+
- The integral part of the amount with a thousand separator, optional and repeatable:
(,\d+)*
- The decimal part, optional :
(\.\d+)?
Wich would give something like that: (USD ?)?(\d+)(,\d+)*(\.\d+)?
You can test it on regex101.com
You can further restrict the number of digits in each parts to avoid false-positive :
(USD ?)?(\d{1,3})(,\d{3})*(\.\d{1,2})?
A final version would be optimized with non-capturing groups unless necessary:
(?:USD ?)?(?:\d{1,3})(?:,\d{3})*(?:\.\d{1,2})?
Edit: the test case you provided uses incoherent use of decimal separators (sometime ".", sometimes ","). If you really want to match that, you can use a character class like this :
(?:USD ?)?(?:\d{1,3})(?:,\d{3})*(?:[.,]\d{1,2})?
Which matches every number in your example :
