用引号和括号提取字符串

时间:2013-11-12 11:15:30

标签: regex preg-match-all pcre

我的字符串测试是:

My name is "Ralph" ("France" is my country, "123" my age, ... , "an other text", ...)

我希望在引号中使用字符串,但只能在括号中使用。在我的示例中:字符串France123

我测试了这种模式:

#\(.*"(.*)".*\)#

但它只匹配最后一个字符串123(我使用preg_match_all(),所以它应该返回每个结果,不是吗?)

如果我添加U ngreedy选项,它只匹配第一个字符串France。所以我不明白为什么没有U选项它不贪心,有没有办法用引号和括号中的字符串获取?

谢谢, RaphaëlN。

3 个答案:

答案 0 :(得分:0)

保持简单,分两步完成:

$s = 'My name is "Ralph" ("France" is my country, "123" my age) and "I" am. ';
$str = preg_replace('#^.*?\(([^)]*)\).*$#', '$1', $s);
if (preg_match_all('/"([^"]*)"/', $str, $arr))
   print_r($arr[0]);

输出:

Array
(
    [0] => "France"
    [1] => "123"
)

答案 1 :(得分:0)

这应该适合你:

\("([^"]+)".+?"(.+)"

说明:

\(" - 匹配括号和双引号

([^"]+)" - 捕获双引号内的所有内容

.+?" - 匹配下一个双引号的任何内容

(.+) - 捕捉不是双引号的所有内容

" - 匹配上一个双引号

只要您的样本数据与给定的完全相同,正则表达式就可以正常工作

答案 2 :(得分:0)

我能让这个工作的唯一方法是使用:

$subject = 'My 00123450 "Ralph" ("France" is my country, "123" my age, ... , "an other text", ...)';

$pattern =  '/\((?:[^"\)]*"(.*?)")?(?:[^"\)]*"(.*?)")?(?:[^"\)]*"(.*?)")?[^"]*?\)/';
preg_match_all($pattern, $subject, $matches);

for ($i = 1; $i < count($matches); $i++)
{
    print($i.': '.$matches[$i][0].";\n");
}

<强>输出:

1: France; 
2: 123; 
3: an other text;

正则表达式只适用于最多 3次出现的“引用字符串”在一组括号内。但是,您可以将正则表达式字符串扩展为抓取最多 N次出现,如下所示:

在每组括号中找到1到N引用字符串的正则表达式是:

n=1 /\((?:[^"\)]*"(.*?)")?[^"]*?\)/
n=2 /\((?:[^"\)]*"(.*?)")?(?:[^"\)]*"(.*?)")?[^"]*?\)/
n=3 /\((?:[^"\)]*"(.*?)")?(?:[^"\)]*"(.*?)")?(?:[^"\)]*"(.*?)")?[^"]*?\)/

要查找1-N字符串,请重复(?:[^"\)]*"(.*?)")?部分N次。对于每组括号内的1-100个字符串,您必须重复该部分100次 - 显然正则表达式将开始非常缓慢地进行评估。

我意识到这绝不是理想的,但它是我在1遍解决方案上的最大努力。

通过2次:

$subject = 'My name is "Ralph" ("France" is my country, "123" my age, ... , "an other text", ...)';

$pattern =  '/\(.*?\)/';
preg_match_all($pattern, $subject, $matches);

$pattern2 =  '/".*?"/';
preg_match_all($pattern2, $matches[0][0], $matches2);

print_r($matches2);

两次传递产生正确的输出。热切地等待一个答案,显示如何在1中做到这一点。我已经尝试了我能想到的每一个变化,但不能让它包括重叠匹配。