如何找到两个字符之间的所有模式?

αғs*_*нιη 6 command-line regex text-processing

我试图找到一对双引号之间的所有模式。假设我有一个内容如下所示的文件:

first matched is "One". the second is here"Two "
and here are in second line" Three ""Four".
Run Code Online (Sandbox Code Playgroud)

我想下面的话作为输出:

One
Two
Three
Four
Run Code Online (Sandbox Code Playgroud)

如您所见,输出中的所有字符串都在一对引号之间。

我试过的是这个命令:

grep -Po ' "\K[^"]*' file
Run Code Online (Sandbox Code Playgroud)

如果我在第一对"标记之前有一个空格,则上面的命令可以正常工作。例如,如果我的输入文件包含以下内容,它就可以工作:

first matched is "One". the second is here "Two "
and here are in second line " Three " "Four".
Run Code Online (Sandbox Code Playgroud)

我知道我可以用多个命令组合来做到这一点。但我正在寻找一个命令并且多次使用它。例如:下面的命令

grep -oP '"[^"]*"' file | grep -oP '[^"]*'
Run Code Online (Sandbox Code Playgroud)

如何仅使用一个命令来实现/打印我的所有模式?

回复评论:删除一对引号内匹配模式周围的空格对我来说并不重要,但如果命令也支持它会更好。以及我的文件包含嵌套引号,如"foo "bar" zoo". 并且所有引用的单词都在单独的行中,并且不会扩展为多行。

提前致谢。

ter*_*don 8

首先,您的grep -Po '"\K[^"]*' file想法失败了,因为grep"One"和 都". the second is here"视为引号内。就个人而言,我可能会这样做

$ grep -oP '"[^"]+"' file | tr -d '"'
One
Two 
 Three 
Four
Run Code Online (Sandbox Code Playgroud)

但这是两个命令。要使用单个命令执行此操作,您可以使用以下命令之一:

  1. 珀尔

    $ perl -lne '@F=/"\s*([^"]+)\s*"/g; print for @F' file 
    One
    Two 
    Three 
    Four
    
    Run Code Online (Sandbox Code Playgroud)

    在这里,@F数组保存了正则表达式的所有匹配项(一个引号,后跟尽可能多的非-"直到下一个")。在print for @F仅仅表示“打印的每一个元素@F

  2. 珀尔

    $ perl -F'"' -lne 'for($i=1;$i<=$#F;$i+=2){print $F[$i]}' file 
    One
    Two 
     Three 
    Four
    
    Run Code Online (Sandbox Code Playgroud)

    要从每个匹配项中删除前导/尾随空格,请使用以下命令:

    perl -F'"' -lne 'for($i=1;$i<=$#F;$i+=2){$F[$i]=~s/^\s*|\s$//; print $F[$i]}' file 
    
    Run Code Online (Sandbox Code Playgroud)

    在这里,Perl 的行为类似于awk. 该-a开关使其自动将输入行拆分为由 给出的字符上的字段-F。自从我给了它",字段是:

    $ perl -F'"' -lne 'for($i=0;$i<=$#F;$i++){print "Field $i: $F[$i]"}' file 
    Field 0: first matched is 
    Field 1: One
    Field 2: . the second is here
    Field 3: Two 
    Field 0: and here are in second line
    Field 1:  Three 
    Field 2: 
    Field 3: Four
    Field 4: .
    
    Run Code Online (Sandbox Code Playgroud)

    因为我们正在寻找两个连续字段分隔符之间的文本,所以我们知道我们需要每隔一个字段。所以,for($i=1;$i<=$#F;$i+=2){print $F[$i]}将打印我们关心的那些。

  3. 同样的想法,但在awk

    $ awk -F'"' '{for(i=2;i<=NF;i+=2){print $(i)}}' file 
    One
    Two 
     Three 
    Four
    
    Run Code Online (Sandbox Code Playgroud)