<li><b> Some Text:</b></li><li><b> Some Text:</b></li>
<pg>something else</pg> <li><b> Some Text:</b> </li>
<li><b> Some Text:</b></li>
<li><b> Some Text:</b> More Text </li> <li><b> Some Text:</b> More Text </li>
如果这是我的输入字符串和
Some Text:
Some Text:
Some Text:
Some Text: More Text
Some Text: More Text
这是我的输出但我得到的只是
Some Text:
Some Text:
Some Text: More Text
这是我在linux中的shell脚本函数
#!/bin/sh
sed -n -e 's/.*<li>\(.*\)<\/li>.*/\1/p' $1 > temp
sed -e 's/<[<\/b]*>//g' temp >out
请告诉我哪里出错了。
答案 0 :(得分:2)
以下是GNU awk
的一种方法(第一行是空白行):
$ gawk '
RT=="</b>"||RT=="</li>" && NF {
gsub(/^ *| *$/,"")
printf "%s%s",(ORS=!(NR%2)?"":"\n"),$0
}
END { print "\n" }' RS='</?b>|</?li>' file
Some Text:
Some Text:
Some Text:
Some Text:
Some Text:More Text
Some Text:More Text
答案 1 :(得分:1)
如果您不介意使用第三方工具 - 多平台网络抓取工具xidel - 它会变得如此简单为:
xidel file.html -e '/li'
这将提取所有(顶级)li
元素的纯文本内容,并在单独的行上打印以生成所需的输出。
答案 2 :(得分:1)
首先要做的事情是:一般说话,使用一种理解HTML的工具(参见我的其他答案),而不是awk
或sed
进行HTML解析 - 作为@chepner简洁地使用如上所述:
不要用sed或awk解析HTML; sed用于基于行的编辑,awk用于基于字段的任务。两者都不适用于其元素可能跨越多行的一般结构化文本。
因此,下面的解决方案在有限的情况下工作,但不能很好地概括。
@jaypal已经提供了 GNU awk(gawk
) - 具体答案。
这是一个应该使用所有awk
种口味,它们接受正则表达式作为输入记录分隔符(RS
)(例如gawk
,{{1 }}和mawk
):
nawk
符合旧版和POSIX标准的awk -v RS='</?li>\n*' '
/^<b>/ { t=$0; gsub(/<\/?b>/, "", t); gsub(/^ +| +$/, "", t); print t}
' file
版本 - 例如 OSX 中基于BSD的版本 - 只接受单个文字字符。作为awk
,所以上面不会工作;在OSX上,以下RS
命令实现了相同的功能(也适用于Linux):
sed
两种解决方案都会修剪输出行的前导和尾随空格。
答案 3 :(得分:0)
#!/bin/sh
你的第一个sed行并不是你想要它做的: 每行只能匹配一次出现
sed -n -e 's/.*<li>\(.*\)<\/li>.*/\1/p' $1 > temp
this...........................^^
匹配....其余部分(显然不是你所期望的)
一个简单的解决方法是在进行任何其他处理之前将每个</li>
更改为</li> plus linefeed
。
#!/bin/sh
sed -e 's/<\/li>/<\/li>\n/g' "$1" |\
sed -n -e 's/.*<li>\(.*\)<\/li>/\1/p' |\
sed -e 's/<[\/b]*>//g' >out
我不是专家......其他人可能会有一个更优雅的解决方案