【问题标题】:Find a regexp in awk在 awk 中查找正则表达式
【发布时间】:2015-02-18 02:09:02
【问题描述】:

我有这样一行的文件:

<div class="cell contentCell bbActiveRow" tabindex="-1" style="width: 150px; left: 77px; display: block;" cellposition="15,2"><div class="cell contentCell bbActiveRow last-child" tabindex="-1" style="width: 150px; left: 697px; display: block;" cellposition="15,6">159</div></div><div class="contentRow bb_row" rowindex="16" style="display: block; top: 429px;"><div class="cell first-child " title="Go to box" tabindex="-1" role="linkAction" cellposition="16,0"><span class="pre-child" style="background-color:#16A765;">&nbsp;</span><span class="link" role="link">&nbsp;</span></div>

我想抓住的重要一点是 159 in:

,6">159</div>

我可以用 grep 很好地理解它:

cat c |grep  ',6\">[0-9]\+<'

现在,我想做的实际上是捕获数字本身 (159) 并将其打印出来。 请注意,我拥有的实际文件有几行。理想情况下,只会打印出数字。

我以为我可以用 awk 做到这一点:

cat c | awk ' /,6\">([0-9]\+)/ { print $1 } '

但是不,没有任何东西被打印出来。 准备好正则表达式,并且知道文件中有几行包含与表达式匹配的条目(具有不同的数字),您将如何挤出这些数字?

【问题讨论】:

  • 在我看来并不是最好的方法;但是如果你想那样做,你可以使用 gawk 吗?

标签: regex shell awk


【解决方案1】:

这个 oneliner 是一种替代方法(使用 xpath 表达式匹配包含以 ',6' 结尾的 cellposition 属性值的 div 元素):

# xmllint --html test.html --xpath '//div[substring(@cellposition, string-length(@cellposition) - 1)=",6"]/text()' 
159

【讨论】:

  • 这可能是最好的方法+1
  • 很好,虽然 xmllint 不是所有平台的标准,不幸的是(带有 OS X 和 一些 Linux 发行版(例如,Fedora),但值得注意的是不是 Ubuntu)。
  • @mklement0 是的,这个网站上有一些人因为试图解析 html 中的文本而被残忍对待....
【解决方案2】:

务实的做法:

cat c | grep -o ',6\">[0-9]\+<' | awk -F'<|>' '{ print $2 }'
  • -o 导致 grep 只报告每行的匹配部分。
  • 然后awk -F'&lt;|&gt;' '{ print $2 }' 提取&gt;&lt; 之间的令牌。

至于为什么你的awk 命令不起作用:

  • awk 使用扩展正则表达式,其中 + 不得转义为 \+ 才能被识别为量词。
  • 即使修复了该问题,该命令也不起作用,因为默认情况下,awk 按空格分割,因此$2 将在每个匹配项上仅报告第二个 空格 分隔的标记行,与导致匹配的正则表达式无关。

顶部的解决方案甚至可以在一行上找到 多个 匹配项,但如果我们假设最多有 1 个,那么相对 这样做很简单全部在awk如果你有 GNU awk:

cat c | gawk '{ m=gensub(/^.*,6\">([0-9]+)<.*$/, "\\1", "1"); if (m != $0) print m }'    
  • 非 POSIX gensub() 替换正则表达式匹配项并返回替换,同时至关重要的是还支持反向引用,而 POSIX sub()gsub() 函数不支持。
  • 上面匹配整行,然后仅用捕获的数字替换它(通过(转义)反向引用\1),并将结果存储在变量中。如果变量不等于输入行,则捕获并打印匹配项。

虽然只有 POSIX awk 功能的解决方案是可能的(使用 match()RSTARTRLENGTHsplit()),但它会很麻烦。


最后,如果你有xmllint(OS X 有,一些 Linux 发行版),考虑guido's answer 的解决方案,执行实际的 HTML 解析并应用XPath 查询,因此更健壮。

【讨论】:

  • 我从来不知道 grep 中的 -o 选项。那是关键!谢谢!
  • @Merc:很高兴听到这个消息。 -o 不是 POSIX 的一部分(参见 man.cx/grep),但至少 GNU grep 和 BSD/OS X grep 确实支持它。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多