仅捕获以 's_' 开头并包含数字和字母混合的字符串中的数字
Capture only the numbers from a string beginning with 's_' and containing a mix of numbers and letters
我想从此字符串中提取所有数字:'s_0a1f2d4e3c10b'。字符串必须遵循此模式 's_NumberLetterNumberLetter...'
我写了这个匹配整个字符串的正则表达式:
/^q_(?:\d+[a-f])+$/
问题是我不知道如何只捕获数字。当我在 \d+ 两边加上方括号时,正则表达式只匹配最后一个数字 (10)。
这是带方括号的正则表达式:
^q_(?:(\d+)[a-f])+$
当然我可以使用 preg_match_all('/\d+/', 's_0a1f2d4e3c10b', $matches)
但我希望字符串以 's_' 开头并且我只想使用一个正则表达式(如果可能的话)。
我想要的 s_0a1f2d4e3c10b
输出:
array(0, 1, 2, 4, 3, 10)
您可以使用 preg_replace,像这样:
$count = null;
$returnValue = preg_replace('/[^0-9]+/', '', 's_0a1f2d4e3c10b', -1, $count);
这将从字符串中删除所有非数字字符。
$returnValue
将包含 '0124310'
而 $count
将包含 7
(删除的字符数)
不确定您想要的是哪个结果,因为您似乎想要保留 s_,但将数字(不是数字)分隔成值。它要么是一个字符串,要么是一个数字列表,不能两者兼而有之。
preg_match_all('/s_\d+|\d+/', 's_0a1f2d4e3c10b', $matches)
将 return 一个数组,第一个值在开头保留 s_
。
preg_match_all('/s_\d+|\d+/', 's_0a1f2d4e3c10b', $matches)
将 return 一个数组,第一个值是 只有 s_
然后后续值是数字。
您建议的 preg_match_all('/\d+/', 's_0a1f2d4e3c10b', $matches)
将仅 return 数组中的数字,如果您将它们连接到字符串,则可以添加 s_
前缀。
您需要正则表达式中的“继续”元字符 (\G
) 才能在单个 preg_
调用中干净地执行此任务。
只有当子字符串以 s_
开头时才能开始匹配。然后匹配只能在坚持交替数字和小写字母模式的情况下继续。
\G
实际上允许从字符串的开头或最后匹配结束的位置开始匹配。要拒绝从字符串开头匹配的功能,请添加包含插入符号 ((?!^)
) 的否定前瞻。
\K
表示重新开始这个全字符串匹配(或者换句话说,“忘记”任何以前匹配的字符)。这避免了使用捕获组,否则会不必要地膨胀匹配的输出数组。
代码:(Demo)
$tests = [
'This string s_0a1f2d4e3c10b is foo.',
's_1a23b456c789',
'b_9d9d9d9d9d',
's_1e2f3a4b'
];
foreach ($tests as $test) {
var_export(
preg_match_all(
'~(?:s_|\G(?!^)[a-z]+)\K\d+~',
$test,
$matches
)
? $matches[0]
: []
);
echo "\n---\n";
}
输出:
['0', '1', '2', '4', '3', '10']
---
['1', '23', '456', '789']
---
[]
---
['1', '2', '3', '4']
---
我想从此字符串中提取所有数字:'s_0a1f2d4e3c10b'。字符串必须遵循此模式 's_NumberLetterNumberLetter...' 我写了这个匹配整个字符串的正则表达式:
/^q_(?:\d+[a-f])+$/
问题是我不知道如何只捕获数字。当我在 \d+ 两边加上方括号时,正则表达式只匹配最后一个数字 (10)。 这是带方括号的正则表达式:
^q_(?:(\d+)[a-f])+$
当然我可以使用 preg_match_all('/\d+/', 's_0a1f2d4e3c10b', $matches)
但我希望字符串以 's_' 开头并且我只想使用一个正则表达式(如果可能的话)。
我想要的 s_0a1f2d4e3c10b
输出:
array(0, 1, 2, 4, 3, 10)
您可以使用 preg_replace,像这样:
$count = null;
$returnValue = preg_replace('/[^0-9]+/', '', 's_0a1f2d4e3c10b', -1, $count);
这将从字符串中删除所有非数字字符。
$returnValue
将包含 '0124310'
而 $count
将包含 7
(删除的字符数)
不确定您想要的是哪个结果,因为您似乎想要保留 s_,但将数字(不是数字)分隔成值。它要么是一个字符串,要么是一个数字列表,不能两者兼而有之。
preg_match_all('/s_\d+|\d+/', 's_0a1f2d4e3c10b', $matches)
将 return 一个数组,第一个值在开头保留 s_
。
preg_match_all('/s_\d+|\d+/', 's_0a1f2d4e3c10b', $matches)
将 return 一个数组,第一个值是 只有 s_
然后后续值是数字。
您建议的 preg_match_all('/\d+/', 's_0a1f2d4e3c10b', $matches)
将仅 return 数组中的数字,如果您将它们连接到字符串,则可以添加 s_
前缀。
您需要正则表达式中的“继续”元字符 (\G
) 才能在单个 preg_
调用中干净地执行此任务。
只有当子字符串以 s_
开头时才能开始匹配。然后匹配只能在坚持交替数字和小写字母模式的情况下继续。
\G
实际上允许从字符串的开头或最后匹配结束的位置开始匹配。要拒绝从字符串开头匹配的功能,请添加包含插入符号 ((?!^)
) 的否定前瞻。
\K
表示重新开始这个全字符串匹配(或者换句话说,“忘记”任何以前匹配的字符)。这避免了使用捕获组,否则会不必要地膨胀匹配的输出数组。
代码:(Demo)
$tests = [
'This string s_0a1f2d4e3c10b is foo.',
's_1a23b456c789',
'b_9d9d9d9d9d',
's_1e2f3a4b'
];
foreach ($tests as $test) {
var_export(
preg_match_all(
'~(?:s_|\G(?!^)[a-z]+)\K\d+~',
$test,
$matches
)
? $matches[0]
: []
);
echo "\n---\n";
}
输出:
['0', '1', '2', '4', '3', '10']
---
['1', '23', '456', '789']
---
[]
---
['1', '2', '3', '4']
---