AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / ubuntu / 问题 / 548742
Accepted
αғsнιη
αғsнιη
Asked: 2014-11-13 05:10:41 +0800 CST2014-11-13 05:10:41 +0800 CST 2014-11-13 05:10:41 +0800 CST

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

  • 772

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

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". 并且所有引用的单词都在单独的行中,并且不会扩展为多行。

提前致谢。

command-line
  • 5 5 个回答
  • 22036 Views

5 个回答

  • Voted
  1. Best Answer
    terdon
    2014-11-13T05:43:49+08:002014-11-13T05:43:49+08:00

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

    $ grep -oP '"[^"]+"' file | tr -d '"'
    One
    Two 
     Three 
    Four
    

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

    1. Perl

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

      在这里,@F数组包含正则表达式的所有匹配项(引号,后跟尽可能多的非-"直到下一个")。print for @Fjust的意思是“打印@F.

    2. Perl

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

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

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

      在这里,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: .
      

      因为我们正在寻找两个连续字段分隔符之间的文本,所以我们知道我们需要每隔一个字段。因此,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
      
    • 8
  2. glenn jackman
    2014-11-13T06:46:26+08:002014-11-13T06:46:26+08:00

    关键是使用表达式中的引号。很难用一个 grep 命令做到这一点。这是一个 perl 单行代码:

    perl -0777 -nE 'say for /"(.*?)"/sg' file
    

    这吞噬了整个输入并打印出匹配的捕获部分。即使引号内有换行符,它也能正常工作,尽管这样就很难区分有无换行符的元素。为此,请使用不同的字符作为输出记录分隔符,例如空字符

    perl -0777 -lne 'print for /"(.*?)"/sg} BEGIN {$\="\0"' <<DATA | od -c
    blah "first" blah "second
    quote with newline" blah "third"
    DATA
    
    0000000   f   i   r   s   t  \0   s   e   c   o   n   d  \n   q   u   o
    0000020   t   e       w   i   t   h       n   e   w   l   i   n   e  \0
    0000040   t   h   i   r   d  \0
    0000046
    
    • 2
  3. Avinash Raj
    2014-11-17T22:22:49+08:002014-11-17T22:22:49+08:00

    这可以通过下面的 grep one liner 实现,我假设你有平衡的引号。

    grep -oP '"\s*\K[^"]+?(?=\s*"(?:[^"]*"[^"]*")*[^"]*$)' file
    

    例子:

    $ cat file
    first matched is "One". the second is here"Two "
    and here are in second line" Three ""Four".
    $ grep -oP '"\s*\K[^"]+?(?=\s*"(?:[^"]*"[^"]*")*[^"]*$)' file
    One
    Two
    Three
    Four
    

    另一种通过 PCRE verb (*SKIP)(*F) ,

    $ grep -oP '[^"]+(?=(?:"[^"]*"[^"]*)*[^"]*$)(*SKIP)(*F)|\s*\K[^"]+(?=\b\s*)' file
    One
    Two
    Three
    Four
    
    • 1
  4. αғsнιη
    2014-12-21T11:45:28+08:002014-12-21T11:45:28+08:00

    使用sed:

    sed 's/[^"]*"\([^"]\+\)"[^"]*/\1\n/g' file
    

    [^"]*
    

    ^开头的表示[^"]* ...字符类中列出的字符不应该匹配(只匹配单个")。该*方法"可以出现零次或多次。

    "\([^"]\+\)"
    

    里面的一切\(...\)都是匹配组。匹配组之外的第一个字符是开始匹配。下面是一个字符类[^"](它匹配除 之外的每个字符")。量词表示输入文件中\+的引号 () 之间必须至少有一个字符。"..."然后\),匹配组结束。这个匹配组可以通过它的索引访问\1。

    最后一部分[^"]*与匹配所有内容的第一部分相同,直到下一个"。

    • 0
  5. Sergiy Kolodyazhnyy
    2017-02-06T13:36:44+08:002017-02-06T13:36:44+08:00

    不需要正则表达式的 Python 替代方法(虽然不是很健壮)是逐个字符地处理文本文件中的每一行。

    这是如何工作的基本思想:如果我们看到双引号并且没有升旗 - 升旗,如果我们再次看到它并且升旗 - 降旗。当标志升起时 - 这就是我们知道我们在双引号内的方式,因此我们可以存储后续字符。旗帜降下后,打印我们阅读的内容。

    #!/usr/bin/env python
    from __future__ import print_function
    import sys
    
    flag=False
    quoted_string=[]
    for line in sys.stdin:
        for char in line.strip():
            if char == '"':
               if flag:
                   flag=False
                   if quoted_string:
                      print("".join(quoted_string))
                      quoted_string=[]
               else:
                   flag=True
                   continue 
            if flag:
               quoted_string.append(char)
    

    并试运行:

    $ cat input.txt
    first matched is "One". the second is here"Two "
    and here are in second line" Three ""Four".
    
    $ ./get_quoted_words.py < input.txt                                                                                      
    One
    Two 
     Three 
    Four
    
    • 0

相关问题

  • 如何从命令行仅安装安全更新?关于如何管理更新的一些提示

  • 如何从命令行刻录双层 dvd iso

  • 如何从命令行判断机器是否需要重新启动?

  • 文件权限如何工作?文件权限用户和组

  • 如何在 Vim 中启用全彩支持?

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    如何运行 .sh 脚本?

    • 16 个回答
  • Marko Smith

    如何安装 .tar.gz(或 .tar.bz2)文件?

    • 14 个回答
  • Marko Smith

    如何列出所有已安装的软件包

    • 24 个回答
  • Marko Smith

    无法锁定管理目录 (/var/lib/dpkg/) 是另一个进程在使用它吗?

    • 25 个回答
  • Martin Hope
    Flimm 如何在没有 sudo 的情况下使用 docker? 2014-06-07 00:17:43 +0800 CST
  • Martin Hope
    Ivan 如何列出所有已安装的软件包 2010-12-17 18:08:49 +0800 CST
  • Martin Hope
    La Ode Adam Saputra 无法锁定管理目录 (/var/lib/dpkg/) 是另一个进程在使用它吗? 2010-11-30 18:12:48 +0800 CST
  • Martin Hope
    David Barry 如何从命令行确定目录(文件夹)的总大小? 2010-08-06 10:20:23 +0800 CST
  • Martin Hope
    jfoucher “以下软件包已被保留:”为什么以及如何解决? 2010-08-01 13:59:22 +0800 CST
  • Martin Hope
    David Ashford 如何删除 PPA? 2010-07-30 01:09:42 +0800 CST

热门标签

10.10 10.04 gnome networking server command-line package-management software-recommendation sound xorg

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve