我正在搜索一个多行文本文件,并想要匹配从某个单词到另一个单词的第一个匹配项的字符串:
start
word1
word1
word1
word1
end
word2
word2
word2
start
word3
word3
word3
end
以下是我使用的:grep -Pzo "(?s)start.*?end" file.txt
它从头到尾匹配上面文本字符串中的所有内容,而我只想匹配直到第一次end
出现,即:
start
word1
word1
word1
word1
end
我究竟做错了什么?
不知何故,非贪婪?
量词没有像我预期的那样工作。
感谢您的时间和贡献!
答案1
A贪婪的匹配将包括从第一个start
到最后一个的所有内容end
,因此:
$ grep -Pzo '(?s)start.*end' file.txt
start
word1
word1
word1
word1
end
word2
word2
word2
start
word3
word3
word3
end
你实际看到的是二单独的非贪婪匹配,根据-o
选项在单独的“行”上输出 - 除了使用-Z
,“行”实际上由空字符而不是换行符表示:
$ grep -Pzo '(?s)start.*?end' file.txt
start
word1
word1
word1
word1
endstart
word3
word3
word3
end
由于我们在这里看不到空字节,因此如果添加-b
以指示“行”内两个匹配的字节偏移量,则会更清楚:
$ grep -Pzo -b '(?s)start.*?end' file.txt
0:start
word1
word1
word1
word1
end52:start
word3
word3
word3
end
由于-o
输出是用空值分隔的,因此您可以通过管道传输结果head -z
以获取第一个匹配项:
$ grep -Pzo '(?s)start.*?end' file.txt | head -z -n 1
start
word1
word1
word1
word1
end
或者你可以使用 perl 本身
perl -0777 -nE 'say for /(start.*?end)/s' file.txt
由于省略了标志,因此尽管有for
循环,但仅打印一个匹配项g
。