Regex Optionally match a pattern multiple times
You may validate the string with a positive lookahead triggered at the start of the string, and then match all numbers from the start up to the currency value once the validation succeeds:
'~(?:\G(?!^)|^(?=\d+\.\d+ \d+\.\d+ \d+(?:\.\d+)?(?: \d+)* \$\d))\s*\$?\K\d+(?:\.\d+)?~'
See the regex demo
Details
(?:\G(?!^)|^(?=\d+\.\d+ \d+\.\d+ \d+(?:\.\d+)?(?: \d+)* \$\d))
- either the end of the previous match (\G(?!^)
) or start of a string (^
) that is followed with\d+\.\d+
\d+\.\d+
\d+
- 1+ digits(?:\.\d+)?
- an optional fractional part(?: \d+)*
- 0+ sequences of a space followed with 1+ digits\$\d
- a$
and a digit.
\s*
- 0+ whitespaces\$?
- an optional$
char\K
- match reset operator\d+(?:\.\d+)?
- an int/float number (1+ digits followed with an optional sequence of.
and 1+ digits).
PHP demo:
$strs = ['0.91 0.45 0.69 58 47 45 23 83 90 $595 NO IDL','0.91 0.45 0.69 58 47 45 $595 NO IDL','0.91 0.45 0.69 0.63 58 47 45 $595 NO IDL'];
$rx = '~(?:\G(?!^)|^(?=\d+\.\d+ \d+\.\d+ \d+(?:\.\d+)?(?: \d+)* \$\d))\s*\$?\K\d+(?:\.\d+)?~';
foreach ($strs as $s) {
echo "$s:\n";
if (preg_match_all($rx, $s, $matches)) {
print_r($matches[0]);
echo "---------\n";
} else {
echo "NO MATCH!!!\n---------\n";
}
}
Output:
0.91 0.45 0.69 58 47 45 23 83 90 $595 NO IDL:
Array
(
[0] => 0.91
[1] => 0.45
[2] => 0.69
[3] => 58
[4] => 47
[5] => 45
[6] => 23
[7] => 83
[8] => 90
[9] => 595
)
---------
0.91 0.45 0.69 58 47 45 $595 NO IDL:
Array
(
[0] => 0.91
[1] => 0.45
[2] => 0.69
[3] => 58
[4] => 47
[5] => 45
[6] => 595
)
---------
0.91 0.45 0.69 0.63 58 47 45 $595 NO IDL:
NO MATCH!!!
---------
Regex match a pattern occurring multiple times in a string
You can use
^[0-9]+:[0-9]+, 80:[0-9]+, 443:[0-9]+(, [0-9]+:[0-9]+)+,$
See the regex demo.
Also, consider the awk
solution like
awk '/^[0-9]+:[0-9]+(, [0-9]+:[0-9]+)+,$/ && /80/ && /443/' file
See the online demo:
#!/bin/bash
s='0:0, 80:3, 443:0, 8883:0, 9000:0, 9001:0,
0:0, 80:0, 443:1, 8883:0, 9000:0, 9001:0,
0:0, 80:0, 443:0, 8883:0, 9000:0, 9001:0,
0:0, 80:3, 443:1, 8883:0, 9000:0, 9001:0,
0:0, 443:0, 8883:0, 9000:0, 9001:0,
0:0, 80:0, 8883:0, 9000:0, 9001:0,
0:0, 8883:0, 9000:0, 9001:0,'
awk '/^[0-9]+:[0-9]+(, [0-9]+:[0-9]+)+,$/ && /80/ && /443/' <<< "$s"
Output:
0:0, 80:3, 443:0, 8883:0, 9000:0, 9001:0,
0:0, 80:0, 443:1, 8883:0, 9000:0, 9001:0,
0:0, 80:0, 443:0, 8883:0, 9000:0, 9001:0,
0:0, 80:3, 443:1, 8883:0, 9000:0, 9001:0,
Regex with multiple optional groups
Try
^(?:.*?(?P<left>&L.[^&]*))?(?:.*?(?P<center>&C.[^&]*))?(?:.*?(?P<right>&R.[^&]*))?.*$
regex101 demo.
Explanation of the left
group (center
and right
are pretty much the same):
(?:
.*? # consume any preceding text
(?P<left> # then capture...
&L # "&L" literally
. # the character after that
[^&]* # and then everything up to the next "&" character
)
)? # and make the whole thing optional.
P.S.: Your pattern didn't make any of the groups optional. You should've put the ?
after the group, like (?P<left>&L.+)?
.
UPDATE
Since the groups aren't supposed to end at the next &
character, you can try the pattern
(?P<left>&L.+?)?(?P<center>&C.+?)?(?P<right>&R.+?)?$
instead. All I did was to make all groups optional by adding a ?
, and forcing the pattern to consume the entire string by putting the anchor $
at the end.
regex101 demo.
Update: (?:&L(?P<left>.+?))?(?:&C(?P<center>.+?))?(?:&R(?P<right>.+?))?$
won't capture the &L
, &C
and &R
bits.
Regex how to match an optional character
Use
[A-Z]?
to make the letter optional. {1}
is redundant. (Of course you could also write [A-Z]{0,1}
which would mean the same, but that's what the ?
is there for.)
You could improve your regex to
^([0-9]{5})+\s+([A-Z]?)\s+([A-Z])([0-9]{3})([0-9]{3})([A-Z]{3})([A-Z]{3})\s+([A-Z])[0-9]{3}([0-9]{4})([0-9]{2})([0-9]{2})
And, since in most regex dialects, \d
is the same as [0-9]
:
^(\d{5})+\s+([A-Z]?)\s+([A-Z])(\d{3})(\d{3})([A-Z]{3})([A-Z]{3})\s+([A-Z])\d{3}(\d{4})(\d{2})(\d{2})
But: do you really need 11 separate capturing groups? And if so, why don't you capture the fourth-to-last group of digits?
Regex match pattern with optional character and min/max length
You may use this regex with gnu grep
using -P
(PCRE):
grep -P '^X(?!([^-]*-){2})(?=[^A-Z]*[A-Z])[A-Z\d-]{3,6}$' file
XABC
XA-BC8D
X-ABC
XB72D-
RegEx Demo
RegEx Details:
^
: StartX
: Match letterX
(?!([^-]*-){2})
: Negative lookahead to assert that there are never more than one hyphens ahead(?=[^A-Z]*[A-Z])
: Positive lookahead to assert presence of at least one uppercase letter ahead[A-Z\d-]{3,6}
: Match an uppercase letter or digit or-
3 to 6 times$
: End
If you don't have gnu grep
installed then you may consider this awk
:
awk -F- 'NF<3 && /^X[A-Z0-9-]{3,6}$/ && /.[A-Z]/' file
XABC
XA-BC8D
X-ABC
XB72D-
Regex optional matching for multiline patterns
Replace match of [\n\r]+(?:[-]+[\n\r]+)?\s*junkhere:\s*[\n\r][\s\S]*
with empty string.
Test it here: http://regexr.com?37edu and here: http://regexr.com?37ee1
In Java you have to double escape characters:
= text.replaceAll("[\\n\\r]+(?:[-]+[\\n\\r]+)?\\s*junkhere:\\s*[\\n\\r][\\s\\S]*", "");
How to add an optional string or end the string with Regex?
Try this pattern: ^\$\d+(?:\.\d{2})?$
See Regex Demo
Explanation
^
: Start of the string.\$
: Match with the character$
.\d+
: Match with one or more digits between 0-9.(?:
: Start of the non-captured group.\.
: Match with the dot character.\d{2}
: Match exactly two digits.)
: End of the group.?
: Make everything in the group optional.$
: End of the string.
Note: the $
and .
character in regex means respectively end of the string and everything, so if we want to capture exactly the $
character (not the end of the string) we should escape those characters.
regexp: multiline, non-greedy match until optional string
Use
(?s)\AKey1:\n(?P<Key1>.*)Key2:\n(?P<Key2>.*?)(?:OptionalKey3:\n(?P<OptionalKey3>.*))?\z
See regex proof.
EXPLANATION
--------------------------------------------------------------------------------
(?s) set flags for this block (with . matching
\n) (case-sensitive) (with ^ and $
matching normally) (matching whitespace
and # normally)
--------------------------------------------------------------------------------
\A the beginning of the string
--------------------------------------------------------------------------------
Key1: 'Key1:'
--------------------------------------------------------------------------------
\n '\n' (newline)
--------------------------------------------------------------------------------
(?P<Key1> group and capture to "Key1":
--------------------------------------------------------------------------------
.* any character (0 or more times (matching
the most amount possible))
--------------------------------------------------------------------------------
) end of "Key1"
--------------------------------------------------------------------------------
Key2: 'Key2:'
--------------------------------------------------------------------------------
\n '\n' (newline)
--------------------------------------------------------------------------------
(?P<Key2> group and capture to "Key2":
--------------------------------------------------------------------------------
.*? any character (0 or more times (matching
the least amount possible))
--------------------------------------------------------------------------------
) end of "Key2"
--------------------------------------------------------------------------------
(?: group, but do not capture (optional
(matching the most amount possible)):
--------------------------------------------------------------------------------
OptionalKey3: 'OptionalKey3:'
--------------------------------------------------------------------------------
\n '\n' (newline)
--------------------------------------------------------------------------------
(?P<OptionalKey3> group and capture to "OptionalKey3":
--------------------------------------------------------------------------------
.* any character (0 or more times
(matching the most amount possible))
--------------------------------------------------------------------------------
) end of "OptionalKey3"
--------------------------------------------------------------------------------
)? end of grouping
--------------------------------------------------------------------------------
\z the end of the string
Related Topics
How to Get the Url of Currently Opened Tabs in All Browsers With PHP or JavaScript
Passing an Array to a Query Using a Where Clause
How to Get Previous Month from Selected Month
Laravel: Property [Name] Does Not Exist on This Collection Instance
Dompdf Table Fixed Column Width and Break Long Text
Laravel Drop Down Multiple Values from Db in Drop Down
Laravel Eloquent Get Results Grouped by Days
Getting Date Format M-D-Y H:I:S.U from Milliseconds
How to Extract and Access Data from Json With PHP
How to Send an Email Using PHP
How to Generate Unique Random Value for Each User in Laravel and Add It to Database
How to Find Out If CSV File Fields Are Tab Delimited or Comma Delimited
How to Show Blob Image in HTML
Laravel Convert Query MySQL to Model Query
Laravel - How to Join 2 Tables from Different Db Connection
How to Redirect to the Same Page in PHP