PHP中匹配1000-20000美元金额的复杂正则表达式需求
Got it, let's break this down. You need to count all USD amounts between 1000 and 20000, covering all those tricky formatting variations—like different $ positions, thousand separators, decimals, and suffixes like USD/Dollar.
I'll present two practical approaches: a regex+PHP validation method (more maintainable and less error-prone) and a pure regex method (for strict pattern matching without post-processing).
Approach 1: Regex + PHP Validation (Recommended)
Numeric range checks are way easier to handle in PHP than in regex alone, so this method balances pattern matching with simple validation to avoid edge case headaches.
Step 1: The Format-Matching Regex
This regex catches all valid USD format variations, regardless of the numeric value:
/(?<!\d)(?:\$?\s?(?:\d{1,5}(?:,\d{3})*(?:\.\d{1,2})?)\s?(?:\$|(?:US-)?Dollar|USD)|(?:\d{1,5}(?:,\d{3})*(?:\.\d{1,2})?)\s?(?:\$|(?:US-)?Dollar|USD))(?!\d)/i
Regex Breakdown
(?<!\d): Negative lookbehind to ensure we don't match part of a larger number (e.g., avoid picking "1000" from "11000")\$?\s?: Optional$symbol followed by optional whitespace (covers$1000or$ 1000)\d{1,5}(?:,\d{3})*(?:\.\d{1,2})?: Matches the numeric core:\d{1,5}: 1-5 digits (covers up to 20000)(?:,\d{3})*: Optional thousand separators (e.g.,1,000,12,345)(?:\.\d{1,2})?: Optional decimal with 1-2 digits (e.g.,1000.99,2,500.5)
\s?(?:\$|(?:US-)?Dollar|USD): Optional whitespace followed by$or currency suffix (case-insensitive fordollarvsDollar)(?!\d): Negative lookahead to avoid matching part of a larger number/i: Case-insensitive modifier for flexible suffix matching
Step 2: PHP Implementation
Use preg_match_all to grab all potential matches, then validate each one to check if it falls within 1000-20000:
$text = "Here are some amounts: $1000, 1500 $, 2,500.50 USD, 300, $20, $21000, 20000 US-Dollar, 19,999.99 Dollar"; // Capture all potential USD amounts preg_match_all('/(?<!\d)(?:\$?\s?(?:\d{1,5}(?:,\d{3})*(?:\.\d{1,2})?)\s?(?:\$|(?:US-)?Dollar|USD)|(?:\d{1,5}(?:,\d{3})*(?:\.\d{1,2})?)\s?(?:\$|(?:US-)?Dollar|USD))(?!\d)/i', $text, $matches); $validAmounts = []; foreach ($matches[0] as $match) { // Extract numeric value by stripping non-digit/non-decimal characters $numericStr = preg_replace('/[^\d.]/', '', $match); // Remove duplicate dots (just a safety check) $numericStr = preg_replace('/\.(?=.*\.)/', '', $numericStr); $amount = (float)$numericStr; // Validate range if ($amount >= 1000 && $amount <= 20000) { $validAmounts[] = $match; } } // Get the count of valid matches $count = count($validAmounts); echo "Valid USD amounts found: $count\n"; print_r($validAmounts);
Output
Valid USD amounts found: 5 Array ( [0] => $1000 [1] => 1500 $ [2] => 2,500.50 USD [3] => 20000 US-Dollar [4] => 19,999.99 Dollar )
Approach 2: Pure Regex (Strict Pattern Matching)
If you prefer a regex-only solution (no post-processing), here's a pattern that directly matches only amounts between 1000-20000:
/(?<!\d)(?:\$?\s?(?:(?:1\d{3}(?:,\d{3})?|20,?000)(?:\.\d{1,2})?)\s?(?:\$|(?:US-)?Dollar|USD)|(?:(?:1\d{3}(?:,\d{3})?|20,?000)(?:\.\d{1,2})?)\s?(?:\$|(?:US-)?Dollar|USD))(?!\d)/i
Key Range Restriction
1\d{3}(?:,\d{3})?: Matches 1000-1999 (with or without comma:1000or1,000) and 10000-19999 (10000or10,000to19,999)20,?000: Matches the upper limit, allowing optional comma (20000or20,000)
PHP Usage
$text = "Here are some amounts: $1000, 1500 $, 2,500.50 USD, 300, $20, $21000, 20000 US-Dollar, 19,999.99 Dollar"; preg_match_all('/(?<!\d)(?:\$?\s?(?:(?:1\d{3}(?:,\d{3})?|20,?000)(?:\.\d{1,2})?)\s?(?:\$|(?:US-)?Dollar|USD)|(?:(?:1\d{3}(?:,\d{3})?|20,?000)(?:\.\d{1,2})?)\s?(?:\$|(?:US-)?Dollar|USD))(?!\d)/i', $text, $matches); $count = count($matches[0]); echo "Valid USD amounts found: $count\n"; print_r($matches[0]);
This gives the same result as Approach 1, but note that adjusting the numeric range later will require tweaking the regex instead of just updating a PHP condition.
内容的提问来源于stack exchange,提问作者MarkusHH

