【问题标题】:How to extract two separate groups in regex?如何在正则表达式中提取两个单独的组?
【发布时间】:2022-01-15 13:00:09
【问题描述】:

在本文中,我试图提取以下行的所有标题和页码:

  1. 以 - 开头
  2. 后跟空格
  3. 然后是章节标题
  4. 然后是页面#,像这样:#page=9&

这是我正在使用的原始文本的示例:

|   "Principles of Microeconomics 2e"   (null)
-   "Preface"   #page=9&zoom=0,0,58
|       "1. About OpenStax" #page=9&zoom=0,0,150
|       "2. About OpenStax resources"   #page=9&zoom=0,0,248
|       "3. About Principles of Microeconomics 2e"  #page=9&zoom=0,0,544
|       "4. Additional resources"   #page=13&zoom=0,0,367
|       "5. About the authors"  #page=14&zoom=0,0,58
-   "Chapter 1. Welcome to Economics!"  #page=17&zoom=0,0,58
|       "1.1. What Is Economics, and Why Is It Important?*" #page=18&zoom=0,0,338
|       "1.2. Microeconomics and Macroeconomics*"   #page=22&zoom=0,0,448
|       "1.3. How Economists Use Theories and Models to Understand Economic Issues*"    #page=23&zoom=0,0,565

我当前的正则表达式: (?:\-\s)(["'])(?:(?=(\\?))\2.)*?(?:page=)(?<=\=)(.*?)(?=\&)

当前使用此正则表达式匹配整行,但没有将所需元素放入单独的组中。而且我在执行此分隔时遇到了麻烦。

当前输出: current output

想要的输出:

Match 1: "Preface" #page=9&
Group 1: Preface
Group 2: 9

Match 2: "Chapter 1. Welcome to Economics!"  #page=17&
Group 1: Chapter 1. Welcome to Economics!
Group 2: 17

我试图在一组中提取标题,在另一组中提取页码。 我该怎么做?

【问题讨论】:

    标签: regex awk sed


    【解决方案1】:

    开始

    sed -En 's/^-.*"([^"]+)".*page=([[:digit:]]+).*/\1\n\2/p' file
    
    Preface
    9
    Chapter 1. Welcome to Economics!
    17
    

    sed 不使用 PCRE,因此您没有非捕获括号或环视等


    更新以解决所需的新输出。

    sed 没有任意变量,将很难计算匹配项。使用具有相同正则表达式的 GNU awk:

    gawk '
        match($0, /^-.*"([^"]+)".*page=([[:digit:]]+)/, m) {
            printf "Match %d: %s\n", ++n, m[0]
            printf "Group 1: %s\n", m[1]
            printf "Group 2: %s\n\n", m[2]
        }
    ' file
    
    Match 1: -   "Preface"   #page=9
    Group 1: Preface
    Group 2: 9
    
    Match 2: -   "Chapter 1. Welcome to Economics!"  #page=17
    Group 1: Chapter 1. Welcome to Economics!
    Group 2: 17
    
    

    3 参数 match() 函数需要 GNU awk。

    【讨论】:

      【解决方案2】:

      使用 GNU awk:

      awk 'BEGIN{ FPAT="\".*\"|#page=[0-9]+&" }
           /^- /{
             print "Match", ++m ":", $1, $2;
      
             gsub(/"/, "", $1);               # remove all "
             print "Group 1:", $1;
      
             gsub(/[^0-9]+/, "", $2);         # remove all but numbers
             print "Group 2:", $2;
      
             print ""
           }' file
      

      输出:

      匹配 1:“序言”#page=9& 第一组:前言 第 2 组:9 比赛 2:“第 1 章。欢迎来到经济学!” #page=17& 第 1 组:第 1 章。欢迎来到经济学! 第 2 组:17

      FPAT:描述记录中字段内容的正则表达式。

      【讨论】:

        【解决方案3】:

        使用sed

        $ sed -n '/[^0-9]*.\./s/-[^"]*\("\)\([^#]*\)\("\)\([^0-9]*\([0-9]*\)&\).*/Match 2: \1\2\3\4\nGroup 1: \2\nGroup 2: \5/p
        ;/-/s/-[^"]*\("\)\([^#]*\)\("\)\([^0-9]*\([0-9]*\)&\).*/Match 1: \1\2\3\4\nGroup 1: \2\nGroup 2: \5\n/p' input_file
        

        输出

        Match 1: "Preface"   #page=9&
        Group 1: Preface
        Group 2: 9
        
        Match 2: "Chapter 1. Welcome to Economics!"  #page=17&
        Group 1: Chapter 1. Welcome to Economics!
        Group 2: 17
        

        【讨论】:

          【解决方案4】:

          使用您展示的示例,请尝试关注awk 程序。用 GNU awk 编写和测试。

          awk -v RS='-[[:space:]]+"[^"]*"[[:space:]]+#page=[0-9]+' '
          RT{
            match(RT,/"[^"]*"/,completeValue)
            printf("Match 1: -   %s\nGroup 1: %s\n",RT,completeValue[0])
            match(RT,/#page=[0-9]+/,pageVal)
            split(pageVal[0],actualpageVal,"=")
            print "Group 2: "actualpageVal[2]
          }
          '  Input_file
          

          解释: 简单的解释是,将 RS(记录分隔符)设置为 -[[:space:]]+"[^"]*"[[:space:]]+#page=[0-9]+ 正则表达式。然后在主程序中;匹配" 的第 2 次出现之间的所有内容并创建数组 completeValue(其中包含根据所示示例的完整值)。然后使用 awkprintf 函数打印第 2 条所需的输出行(完整值和第 1 组:一个),然后根据要求再次从页面值中仅抓取数字值并使用数组 actualpageVal 打印。

          【讨论】:

            猜你喜欢
            • 2013-12-21
            • 2015-10-28
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多