【问题标题】:Extract content between html tags <pre> using bash shell command使用 bash shell 命令提取 html 标签 <pre> 之间的内容
【发布时间】:2020-11-28 06:12:50
【问题描述】:

我想在 bash 中使用 shell 脚本解析下面的 html 文本字符串。

    <pre style=\"font-family: helvetica, arial, sans-serif; white-space: pre-wrap; margin: 0;\">peter-2</pre>\n                                    <pre style=\"font-family: helvetica, arial, sans-serif; white-space: pre-wrap; margin: 0;\">peter-1</pre>\n                                    <pre style=\"font-family: helvetica, arial, sans-serif; white-space: pre-wrap; margin: 0;\">peter0</pre>\n                                    <pre style=\"font-family: helvetica, arial, sans-serif; white-space: pre-wrap; margin: 0;\">peter1</pre>\n                                    <pre style=\"font-family: helvetica, arial, sans-serif; white-space: pre-wrap; margin: 0;\">peter2</pre>\n                                    <pre style=\"font-family: helvetica, arial, sans-serif; white-space: pre-wrap; margin: 0;\">peter3</pre>\n                                    <pre style=\"font-family: helvetica, arial, sans-serif; white-space: pre-wrap; margin: 0;\">peter4</pre>\n

预期输出:

peter-2
peter-1
peter0
peter1
peter2
peter3
peter4

我希望 shell 命令基于 &lt;pre 标签而不是基于位置来提取值。

【问题讨论】:

  • Don't Parse XML/HTML With Regex. 我建议使用 XML/HTML 解析器 (xmlstarlet, xmllint ...)。
  • 我不想使用直接命令。我想使用正则表达式,这样我就不必安装任何命令了。
  • &lt;pre\s.*?&gt;(.*?)&lt;\/pre&gt;regex101.com/r/sfanee/1。你可以使用grep -po "&lt;pre\s.*?&gt;(.*?)&lt;\/pre&gt;"之类的命令
  • 这能回答你的问题吗? Parse HTML using shell
  • @mjrezaee 你测试了 grep 吗?我运行它,它不起作用。 grep 命令失败。你运行的是什么操作系统?似乎在 regex101 上选择了正确的字段

标签: regex bash shell unix grep


【解决方案1】:

假设您的输入总是那么常规,并且由于某种原因您不能使用 XML 解析器,而只是想要一些便宜而愉快的东西,然后使用在替换文本中接受 \n 的 sed(例如 GNU sed):

$ sed 's:</pre>:\n:g' file | sed -n 's/.*>//p'
peter-2
peter-1
peter0
peter1
peter2
peter3
peter4

否则在带有任何 sed 的 bash 中:

$ sed 's:</pre>:\'$'\n'':g' file | sed -n 's/.*>//p'
peter-2
peter-1
peter0
peter1
peter2
peter3
peter4

或任何 shell 中的任何 awk:

$ awk '{gsub("</pre>","\n")}1' file | awk 'sub(/.*>/,"")'
peter-2
peter-1
peter0
peter1
peter2
peter3
peter4

【讨论】:

  • 正是我需要的。谢谢@Ed Morton
【解决方案2】:
# xml_read function
# usage: xml_read <filename> <attribute> [<tag>] (default is </string>)
xml_read () {
  local filename="${1//\*/.\*}" attribute="${2//\*/.\*}" tag="${3//\*/.\*}" value
  [ -n "${tag}" ] || tag=string
  [ -n "${filename}" ] && [ -n "${attribute}" ] && \
  value="$(grep -iwhoIrm1 "<${tag} name=\"${attribute}\">.*</${tag}>" "${filename}" 2> /dev/null | cut -d\> -f2)"
  [ -n "${value}" ] && while [ "${value:(-1)}" != "<" ]; do value="${value%?}"; done
  printf '%s' "${value%?}"
}

编辑:

不确定您的输入格式\n 是换行吗? cut 基于工作行我添加了一个 sed 以将输入文件修改为可读格式

您的 xml 文件看起来与我的不同。移植的函数可能是这样的

#!bin/bash

# xml_read function
# usage: xml_read <filename> <attribute> [<tag>] (default is </string>)
xml_read () {
  local filename="${1//\*/.\*}" attribute="${2//\*/.\*}" tag="${3//\*/.\*}" value
  [ -n "${tag}" ] || tag=string
  [ -n "${filename}" ] && [ -n "${attribute}" ] && \
  grep -iwhoI "<${tag} ${attribute}=.*>.*</${tag}>" "${filename}" 2> /dev/null | cut -d\> -f2 | cut -d\< -f1
}

# evaluate linefeeds
sed -i 's,\\n,'\\n',g' test.xml

# call function
xml_read test.xml style pre

【讨论】:

  • attribute = style, tag = pre(属性接受星号通配符,如*style)
猜你喜欢
  • 2020-08-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-11-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-05-23
相关资源
最近更新 更多