Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/regex/18.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
带有paren分隔组的tcl regexp_Regex_Tcl_Match - Fatal编程技术网

带有paren分隔组的tcl regexp

带有paren分隔组的tcl regexp,regex,tcl,match,Regex,Tcl,Match,我有一组字符串,看起来像: foo<xyz><123> bar pizza<oregano><tomato><mozzarella> 无论出于何种原因,都不会返回 你知道怎么解决这个问题吗 旁注 我试图解析的实际字符串使用方括号和圆括号作为分隔符。类似于:pizza[large](番茄)(橄榄)(奶酪),其中[term]可以出现0次或1次,而(term)s可以出现0次或更多次。 但由于方括号和圆括号的性质,这需要大量的引用,这可能太分

我有一组字符串,看起来像:

foo<xyz><123>
bar
pizza<oregano><tomato><mozzarella>
无论出于何种原因,
都不会返回

你知道怎么解决这个问题吗

旁注 我试图解析的实际字符串使用方括号和圆括号作为分隔符。类似于:
pizza[large](番茄)(橄榄)(奶酪)
,其中
[term]
可以出现0次或1次,而
(term)
s可以出现0次或更多次。
但由于方括号和圆括号的性质,这需要大量的引用,这可能太分散注意力了,在这里不太有用)

在这种情况下,诀窍是使用相当简单的重新处理和后处理结果:

% regexp -all -inline {^([^<>]+)((?:<[^<>]+>)*)$} foo<xyz><123>
foo<xyz><123> foo <xyz><123>
% regexp -all -inline {[^<>]+} <xyz><123>
xyz 123
%regexp-all-inline{^([^]+)((?:)*)$}foo
福福
%regexp-all-inline{[^]+}
xyz 123
您就快到了,但正在努力使用
()*
,这将无法工作,因为它只捕获组匹配的一次。(我不知道它抓住了最后一场比赛,但因为我很少想要第一场或最后一场,而是全部,所以我使用了不同的方法。)

把这些放在一起,假设你有一个大的多行字符串,其中包含了你想查看的所有片段(例如,因为你从文件中读取了它),你会得到:

set str“foo
酒吧
比萨饼“
#找到匹配行并对其执行第一级提取
foreach{prefix attribs}[regexp-all-line-inline{^([^]+)((?:)*)$}$str]{
#拆分属性名称
设置属性[regexp-all-inline{[^]+}$attribs]
#证明我们真的匹配了他们
放置“prefix='$prefix',attributes=[join$attributes,]”
}
这将产生以下输出:

prefix='foo', attributes=xyz,123 prefix='bar', attributes= prefix='pizza', attributes=oregano,tomato,mozzarella 前缀='foo',属性=xyz,123 前缀class='bar',属性= 前缀='pizza',属性=牛至、番茄、马苏里拉 让我们将其标记化

package require string::token

set lex {[[] LB []] RB [(] LP [)] RP [^][()]+ t}
set str {pizza[large](tomato)(olives)(cheese)}

% set tokens [::string::token text $lex $str]
{t 0 4} {LB 5 5} {t 6 10} {RB 11 11} {LP 12 12} {t 13 18} {RP 19" 19} {LP 20 20} {t 21 26} {RP 27 27} {LP 28 28} {t 29 34} {RP 35 35}
标记化后,我们可以用一种小语言将标记解析或评估为语句:

% set terms [lassign $tokens prefix]

proc t {str beg end} {
    string range $str $beg $end
}
proc LB {str beg end} {
    return "Optional term is: "
}
proc RB args {
    return \n
}
proc LP {str beg end} {
    rename LP {}
    proc LP args {
        return ", "
    }
    return "Arguments are: "
}
proc RP args {}

% puts "Prefix is: [eval [linsert $prefix 1 $str]]"
Prefix is: pizza
% % join [lmap term $terms {eval [linsert $term 1 $str]}] {}
Optional term is: large
Arguments are: tomato, olives, cheese
文件: , , , , , , , , , , , ,

我可能误读了这些要求,但既然您已经在特殊符号中“编码”了所有结构细节,为什么不让Tcl列表机制来完成这项工作呢

set str {foo(xyz)(123)
bar
pizza[large](oregano)(tomato)(mozzarella)}

foreach line [split $str \n] {
    set line [string map {"[" " " "]" " " ")(" " " "(" " {" ")" "} "} $line]
    set suffix [lassign $line prefix]
    lassign $suffix a b
    if {[llength $suffix] == 2} {
      set optional $a
      set attributes $b
    } else {
      set optional ""
      set attributes $a
    }
    puts "prefix='$prefix', optional='$optional', attributes='[join $attributes ,]'"
}

我很抱歉,严格地说,我的回答并没有解决regex的问题。而且比其他回复中的魔法要少;)

如果要将第二个捕获拆分为步骤2,则只需在第二个量化组周围使用捕获组-
“^([^]+)((?:)*)”
。使用内置格式工具时,请注意格式问题:经常在方括号前添加反斜杠。请参阅,使用
{^([^]+)((?:)*)$}
regex,它是否工作得足够好?如果可以,我绝对建议将Tcl REs放在大括号中;它避免了所有反斜杠过多的问题(否则是复杂REs的主要问题),并且几乎所有REs都适合这种处理。@WiktorStribiżew perfect。因为你还没有发布答案,我接受了DonalFellows的答案,这个答案实际上是一样的。分几个步骤做事情通常比试图在一个巨大的单步中完成要简单得多,也不一定慢得多。(您没有使用的一点语法是非捕获括号,
(?:…)
,这使得编写这类内容更加容易。)这是一个有时被称为文本润色的练习。显然,除了测试
字符串映射
结果的列表属性或子列表的预期算术等之外,格式良好的检查是无法实现的。嗯,如果任何删除的单词包含空格怎么办?那你的话太多了。如果有一个不匹配的大括号怎么办?然后就是一个无效的列表。“单词包含空格”可以通过一个额外的(内部)水平的花括号来解决:
{“[”“]”(“\}\{”(“\{\”)“\}\}”}
。这很好,就像在Tcl中一样,原子列表和单元素列表之间没有区别。“无效列表”可以被
字符串捕获的是list
检查,这应该很好,因为要求处理的结果无论如何都应该是一个列表。这并不是说正则表达式或标记器不会更健壮,我在前面的评论中这样说。谢谢你的想法。但是,在我的情况下,我想要的是实际的字符串解析是“用户输入”,所以我不能真正依赖格式良好(尽管我在问题中没有这样说)
% set terms [lassign $tokens prefix]

proc t {str beg end} {
    string range $str $beg $end
}
proc LB {str beg end} {
    return "Optional term is: "
}
proc RB args {
    return \n
}
proc LP {str beg end} {
    rename LP {}
    proc LP args {
        return ", "
    }
    return "Arguments are: "
}
proc RP args {}

% puts "Prefix is: [eval [linsert $prefix 1 $str]]"
Prefix is: pizza
% % join [lmap term $terms {eval [linsert $term 1 $str]}] {}
Optional term is: large
Arguments are: tomato, olives, cheese
set str {foo(xyz)(123)
bar
pizza[large](oregano)(tomato)(mozzarella)}

foreach line [split $str \n] {
    set line [string map {"[" " " "]" " " ")(" " " "(" " {" ")" "} "} $line]
    set suffix [lassign $line prefix]
    lassign $suffix a b
    if {[llength $suffix] == 2} {
      set optional $a
      set attributes $b
    } else {
      set optional ""
      set attributes $a
    }
    puts "prefix='$prefix', optional='$optional', attributes='[join $attributes ,]'"
}