我试图找到一对双引号之间的所有模式。假设我有一个文件,其内容如下所示:
first matched is "One". the second is here"Two "
and here are in second line" Three ""Four".
我想将以下单词作为输出:
One
Two
Three
Four
如您所见,输出中的所有字符串都在一对引号之间。
我试过的是这个命令:
grep -Po ' "\K[^"]*' file
如果我在第一对"
标记之前有一个空格,上面的命令就可以正常工作。例如,如果我的输入文件包含以下内容,它就可以工作:
first matched is "One". the second is here "Two "
and here are in second line " Three " "Four".
我知道我可以通过多个命令组合来做到这一点。但是我正在寻找一个命令并且没有多次使用它。例如:下面的命令
grep -oP '"[^"]*"' file | grep -oP '[^"]*'
我怎样才能只使用一个命令来实现/打印我的所有模式?
回复评论: 删除一对引号内匹配模式周围的空格对我来说并不重要,但如果命令也支持它会更好。而且我的文件包含嵌套引号,如"foo "bar" zoo"
. 并且所有引用的单词都在单独的行中,并且不会扩展为多行。
提前致谢。
首先,您的
grep -Po '"\K[^"]*' file
想法失败了,因为grep
将"One"
和都". the second is here"
视为引号内。就个人而言,我可能会这样做但这是两个命令。要使用单个命令执行此操作,您可以使用以下之一:
Perl
在这里,
@F
数组包含正则表达式的所有匹配项(引号,后跟尽可能多的非-"
直到下一个"
)。print for @F
just的意思是“打印@F
.Perl
要从每个匹配项中删除前导/尾随空格,请使用:
在这里,Perl 表现得像
awk
. 该-a
开关使它自动将输入行拆分为由 给出的字符的字段-F
。因为我已经给了它"
,字段是:因为我们正在寻找两个连续字段分隔符之间的文本,所以我们知道我们需要每隔一个字段。因此,
for($i=1;$i<=$#F;$i+=2){print $F[$i]}
将打印我们关心的那些。同样的想法,但在
awk
:关键是使用表达式中的引号。很难用一个 grep 命令做到这一点。这是一个 perl 单行代码:
这吞噬了整个输入并打印出匹配的捕获部分。即使引号内有换行符,它也能正常工作,尽管这样就很难区分有无换行符的元素。为此,请使用不同的字符作为输出记录分隔符,例如空字符
这可以通过下面的 grep one liner 实现,我假设你有平衡的引号。
例子:
另一种通过 PCRE verb (
*SKIP)(*F)
,使用
sed
:^
开头的表示[^"]* ...
字符类中列出的字符不应该匹配(只匹配单个"
)。该*
方法"
可以出现零次或多次。里面的一切
\(...\)
都是匹配组。匹配组之外的第一个字符是开始匹配。下面是一个字符类[^"]
(它匹配除 之外的每个字符"
)。量词表示输入文件中\+
的引号 () 之间必须至少有一个字符。"..."
然后\)
,匹配组结束。这个匹配组可以通过它的索引访问\1
。最后一部分
[^"]*
与匹配所有内容的第一部分相同,直到下一个"
。不需要正则表达式的 Python 替代方法(虽然不是很健壮)是逐个字符地处理文本文件中的每一行。
这是如何工作的基本思想:如果我们看到双引号并且没有升旗 - 升旗,如果我们再次看到它并且升旗 - 降旗。当标志升起时 - 这就是我们知道我们在双引号内的方式,因此我们可以存储后续字符。旗帜降下后,打印我们阅读的内容。
并试运行: