在我的脚本中,我得到一个如下所示的字符串:
Reading thisfile.txt
"lib" maps to directory somedir/work.
"superlib" maps to directory somedir/work.
"anotherlib" maps to directory somedir/anotherlib.
** Error: (errorcode) Cannot access file "somedir/anotherlib". <--
No such file or directory. (errno = ENOENT) <--
Reading anotherfile.txt
.....
但带有错误代码的两条带标记的行只会不时出现。
我正在尝试使用regexpression将Reading thisfile.txt
之后的行放到Reading anotherfile.txt
之前的行,或者**
之前的行,如果它在result
之前。
所以"lib" maps to directory somedir/work.
"superlib" maps to directory somedir/work.
"anotherlib" maps to directory somedir/anotherlib.
在每种情况下应该是这样的:
set pattern ".*Reading thisfile.txt\n(.*)\n.*Reading .*$"
我试过这个正则表达式:
regexp -all $pattern $data -> result
然后我做
set pattern ".*Reading thisfile.txt\n(.*)\n.*\[\*|Reading\].*$"
但是只有在没有错误消息的情况下才有效。 所以我试图寻找*。
** Error
但这也行不通。 set pattern ".*Reading thisfile.txt\n(.*)\n.*\*?.*Reading .*$"
的部分仍在那里。
我想知道为什么。这个甚至不编译:
{{1}}
任何想法如何找到并且不匹配*?
答案 0 :(得分:1)
从您编写正则表达式的方式来看,您将不得不使用大括号:
set pattern {.*Reading thisfile\.txt\n(.*)\n.*\*?.*Reading .*$}
如果使用引号,则必须使用:
set pattern ".*Reading thisfile\\.txt\n(.*)\n.*\\*?.*Reading .*$"
即。基本上放了第二个反斜杠来逃避第一个。
以上将能够抓住一些东西;虽然是第一个和最后一个Reading
之间的所有内容。
如果您想从Reading thisfile.txt
匹配到以星号开头的下一行,那么您可以使用:
set pattern {^Reading thisfile\.txt\n(.*?)\n(?=^Reading|^\*)}
regexp -all -lineanchor -- $pattern $data -> result
(?=^Reading|^\*)
是一个积极的向前看,我将您的(.*)
更改为(.*?)
,以便您真正得到所有事件,而不是从第一个到Reading
。< / p>
如果Reading
或*
位于前方并且都在新行上开始,则前瞻性前瞻将匹配。
-lineanchor
会使^
在每行的开头而不是在字符串的开头匹配。
我忘了提及如果你有多个匹配,你必须set
正则表达式的结果并使用-inline
修饰符而不是使用上面的结构(否则你&#39) ; ll只获取最后一个子匹配)...
set results [regexp -all -inline -lineanchor -- $pattern $data]
foreach {main sub} $results {
puts $sub
}
答案 1 :(得分:1)
我不熟悉tcl,但是下面的正则表达式会给你匹配,其中第一个捕获组包含文件名,第二个捕获组包含你想要的所有行:
^Reading ([^\n]*)\n((?:[^\n]|\n(?!Reading|\*\*))*)
基本上(?:[^\n]|\n(?!Reading|\*\*))*
正在说“匹配任何不是换行符的字符或不跟Reading
或**
< / em>的
我从杰里的答案中得到的是你在tcl中定义的那样:
set pattern {^Reading ([^\n]*)\n((?:[^\n]|\n(?!Reading|\*\*))*)}