Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/regex/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/perl/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Regex Perl正则表达式来匹配未包含在引号中的字符串_Regex_Perl - Fatal编程技术网

Regex Perl正则表达式来匹配未包含在引号中的字符串

Regex Perl正则表达式来匹配未包含在引号中的字符串,regex,perl,Regex,Perl,我试图编写正则表达式来匹配不在引号内的字符串(双引号或单引号),但到目前为止,我所能做的最好的事情是循环遍历字符串的所有字符。必须有一个更简单、更优雅的解决方案 示例:如果尝试将foo替换为bar字符串hello foo会变成你好吧,但您所说的字符串“我的名字是foo”将保持不变 任何人都可以用regexp来帮助实现上述功能吗?更新:快速总结:虽然你需要“平衡组”来真正处理这个问题,但简单的回答是,如果你也需要单引号,你就不能这样做。因为这些都是撇号。所以不管怎样,这都会把你搞砸:这时foo说,

我试图编写正则表达式来匹配不在引号内的字符串(双引号或单引号),但到目前为止,我所能做的最好的事情是循环遍历字符串的所有字符。必须有一个更简单、更优雅的解决方案

示例:如果尝试将
foo
替换为
bar
字符串
hello foo会变成
你好吧
,但您所说的字符串“我的名字是foo”
将保持不变


任何人都可以用regexp来帮助实现上述功能吗?

更新:快速总结:虽然你需要“平衡组”来真正处理这个问题,但简单的回答是,如果你也需要单引号,你就不能这样做。因为这些都是撇号。所以不管怎样,这都会把你搞砸:
这时foo说,“这是我的台词!”
平衡会被撇号弄得乱七八糟。您需要构建一个自定义的解析引擎

注意:如果这是用于HTML属性。。。我已经编写了一个正则表达式,它完全按照您所说的那样正确地解析它们,我相信它可以在Perl中工作。但这也依赖于分隔符,如
=
符号和其他HTML结构。但在90%的情况下,XML/HTML解析器是最好的选择(10%仍然是可能的)

正如我在对你的问题的评论中提到的,更多的例子会给出更具体的答案。以下是您有限示例的答案:

^([^"']*?)foo([^"']*)$
对于中间正则表达式编写器来说,Lookarounds很容易,但对于代码维护来说很复杂,通常并不需要什么。此外,任何要求您在正则表达式中使用点
的操作通常都不如它所能达到的效率

$1bar$2
替换我的例子,你将获得金牌。但是,正如我的评论所说,这是基于您的基本示例,假设您的整个字符串可能以引号开头和结尾。如果你有不同的例子,他们会有所帮助

附加 只是为了好玩,我要回答你的问题,还有两个选择。选项1是我上面的原始答案

选项2(如Floris所述):

如果是这种情况,引用的文本只会出现在搜索文本之前或之后(本例中为foo),那么答案如下:

^(?:([^"']*?)foo(.*)|(.*?)foo([^"']*))$
选项3(见我下面的评论)


要做到这一点,我们必须计算foo前后的引号数量,以确保它们是偶数,或者它们在.NET正则表达式中被称为“平衡”,在没有其他自定义函数的情况下,这两个选项在您的环境中都不可用。

一种方法,使用负前瞻:

perl -lane 's/foo(?![^"]*"(?:[^"]*"[^"]*")*[^"]*$)/bar/g; print' input
如果前面的引号不是奇数,则表示替换。所以这个假设你在输入中有平衡的引号

输入示例:

示例输出:


我也需要这么做,所以我自己解决了。。。此解决方案不依赖于平衡引号,但如果撇号成对出现,则显然不支持撇号

#!/usr/bin/perl

my @test = ( 'hello foo!',
             '"my name is foo"',
             'foo test "test foo test" test foo test "test foo test" test foo',
             "foo test 'test foo test' test foo test 'test foo test' test foo",
             '"foo test foo"',
             'foo test " foo test' );

foreach ( @test )
{
  s!("[^"]*"|'[^']*')|foo!$1//'bar'!ge;
  print "$_\n";
}

我认为我们需要看到更多的例子。最重要的是:这是你的全部弦吗?或者这是一个较大文档的子字符串?显示两到三个输入示例及其相关的预期结果,我可以为您编写(并解释)一个正则表达式,或者建议一个开销较小的工具。我假设您不担心“双引号级别”——换句话说,您好“兄弟”富,“您”怎么样?被认为引号中有
foo
(虽然从语法上看不是)。你能确认吗?即使给出了有限的描述,我也很确定在
foo
之前或之后可能会有被引用的文本,在这种情况下,我认为你的表达不起作用。
嗨,foo,我说了“你好”
,用你的表达式,找不到与
foo
匹配的。这是正确的。但如果是这样,他需要这样说。他还需要说这是否是一个选项:
他说“你好”,然后foo告诉他“劳尔,再见”
。如果是这样,他需要一个不同的工具,因为只有.NET正则表达式可以处理“嵌套”检查他是否在引号内或引号外。因此,如果他没有详细说明更多信息,我的答案就我相信的正则表达式而言是正确的。我不明白你所说的中级正则表达式编写者是什么意思。你是指熟练的专家和新手之间吗?正确。中级正则表达式编写者可以row lookarounds到处都是,因为它们知道如何工作,但这并不意味着它们是正确的,或者是最有效的,也不意味着将来其他不懂lookarounds的开发人员可以对它们进行维护。在本例中,它们是不必要的。@hwnd Right。您使用了第一个正则表达式,我说它将用作字面上的答案o问题中的有限信息。然后,我的第二个选项匹配使用
$1bar$2
替换,即:。正如它所说,仅当从未引用的
foo
在一个方向上引用数据时,该选项才起作用。我还注意到,如果两边都有数据,则将进入未正确使用的正则表达式ss您使用.NET的平衡,这在这里不是一个选项。正如您在另一篇评论中所说,如果是这样的话,另一个工具可能会更好。在
“foo”条上失败。
。谢谢,通过添加一个额外的char类来修复此问题。请尝试
“foo”foo“foo”bar
没错,将否定类移到了Lookahead的末尾,继续对此进行评论,但最终总是没有,哈哈。很难抵制这个正则表达式的创造性。它几乎完美地解决了foo之后的平衡问题。不幸的是,Perl正则表达式对lookbehinds的支持没有那么宽容。而且,这对正确的sing也不起作用le quotes,如果你在这里的泥水中加上撇号,这并不是一个真正的问题。所以我投了赞成票,因为我喜欢你的创造力。
He said, "Hello", so then Foo told him, "Lawl, bye"
perl -lane 's/foo(?![^"]*"(?:[^"]*"[^"]*")*[^"]*$)/bar/g; print' input
hello foo!
"foo" foo "foo"
foo "hello" foo
"foo" bar
hello bar!
"foo" bar "foo"
bar "hello" bar
"foo" bar
#!/usr/bin/perl

my @test = ( 'hello foo!',
             '"my name is foo"',
             'foo test "test foo test" test foo test "test foo test" test foo',
             "foo test 'test foo test' test foo test 'test foo test' test foo",
             '"foo test foo"',
             'foo test " foo test' );

foreach ( @test )
{
  s!("[^"]*"|'[^']*')|foo!$1//'bar'!ge;
  print "$_\n";
}