如何在正则表达式中提取两个独立的组?

How to extract two separate groups in regex?

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

  1. 以 -
  2. 开头
  3. 后跟空格
  4. 然后是章节标题
  5. 然后是第#页,像这样:#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)(["'])(?:(?=(\?)).)*?(?: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

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

开始于

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

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


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

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

gawk '
    match([=12=], /^-.*"([^"]+)".*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。

使用 GNU awk:

awk 'BEGIN{ FPAT="\".*\"|#page=[0-9]+&" }
     /^- /{
       print "Match", ++m ":", , ;

       gsub(/"/, "", );               # remove all "
       print "Group 1:", ;

       gsub(/[^0-9]+/, "", );         # remove all but numbers
       print "Group 2:", ;

       print ""
     }' 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

FPAT: A regular expression describing the contents of the fields in a record.

使用您显示的示例,请尝试执行以下 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 函数打印 1st 2 所需的输出行(完整值和第 1 组:一个),然后再次根据要求仅从页面值中获取数字值并使用数组 actualpageVal 打印它。