awk 多行非贪婪匹配解决方法

S9o*_*vyF 4 html awk

我正在尝试使用 awk 提取 HTML 列表的内容。一些列表条目是多行的。

示例输入列表:

<ul>
    <li>
        <b>2021-07-21:</b> Lorem ipsum 
    </li>
    <li>
        <b>2021-07-19:</b> Lorem ipsum 
    </li>
    <li><b>2021-07-10:</b> Lorem ipsum</li>
</ul>
Run Code Online (Sandbox Code Playgroud)

我正在使用的命令:

awk -v RS="" '{match($0, /<li>(.+)<\/li>/, entry); print entry[1]}' file.html
Run Code Online (Sandbox Code Playgroud)

电流输出:

        <b>2021-07-21:</b> Lorem ipsum 
    </li>
    <li>
        <b>2021-07-19:</b> Lorem ipsum 
    </li>
    <li><b>2021-07-10:</b> Lorem ipsum
Run Code Online (Sandbox Code Playgroud)

期望的输出:

        <b>2021-07-21:</b> Lorem ipsum 
        <b>2021-07-19:</b> Lorem ipsum 
    <b>2021-07-10:</b> Lorem ipsum

Run Code Online (Sandbox Code Playgroud)

我知道问题是因为列表条目没有用空行分隔。我想过使用非贪婪匹配,但显然 awk 不支持它。有可能的解决方法吗?

Ed *_*ton 9

使用用于多字符 RS 的 GNU awk 和\s用于[[:space:]]

$ awk -v RS='\\s*</?li>\\s*' '!(NR%2)' file
<b>2021-07-21:</b> Lorem ipsum
<b>2021-07-19:</b> Lorem ipsum
<b>2021-07-10:</b> Lorem ipsum
Run Code Online (Sandbox Code Playgroud)

我假设您要么真的不希望在您的问题的预期输出中显示前导空白,要么您不在乎它是否存在。


Rav*_*h13 6

使用您显示的示例,请尝试以下awk代码。用 GNU 编写和测试awk

awk -v RS='</li>' '
match($0,/<li>.*/){
  val=substr($0,RSTART,RLENGTH)
  gsub(/<li>\n*[[:space:]]*|\n*[[:space:]]*$/,"",val)
  print val
}
' Input_file
Run Code Online (Sandbox Code Playgroud)

说明:为以上添加详细说明。

awk -v RS='</li>' '              ##Starting awk program from here and setting RS as </li> here.
match($0,/<li>.*/){              ##Matching <li> till end of line here.
  val=substr($0,RSTART,RLENGTH)  ##Creating val which has matched regex value here.
  gsub(/<li>\n*[[:space:]]*|\n*[[:space:]]*$/,"",val)  ##Globally substituting <li> followed by 0 or more new lines followed by 0 or more spaces OR substituting ending new lines or spaces with NULL in val.
  print val                      ##Printing val here.
}
' Input_file                     ##Mentioning Input_file name here.
Run Code Online (Sandbox Code Playgroud)