在Shell参数扩展中使用模式

时间:2013-11-27 10:43:02

标签: bash

我正在阅读一个页面并尝试从中提取一些数据。我有兴趣使用bash,经过几个链接之后,我才知道“Shell参数扩展”可能会有所帮助,但我发现在我的脚本中使用它很困难。我知道使用 sed 可能会更容易,但据我所知,我想知道如何在 bash 中实现这一点。

shopt -s extglob

str='My work</u><br /><span style="color: rgb(34,34,34);"></span><span>abc-X7-27ABC | </span><span style="color: rgb(34,34,34);">build'
echo "${str//<.*>/|}"

我希望我的输出如下:My work|abc-X7-27ABC |build

我想过检查它是否只接受单词而不是模式,而且它似乎正在使用单词。

例如,
echo "${str//span style/|}"可以工作但是 echo "${str//span.*style/|}"没有

另一方面,我在其中一个链接中看到 接受模式。我很困惑,为什么它不能与我在上面使用的模式一起工作。

How to make sed do non-greedy match? (用户konsolebox的解决方案)

2 个答案:

答案 0 :(得分:3)

你犯的一个错误是混合shell globbing和regex。在shell glob中,点的字面意思是点字符,而不是任何字符的0或更多。

如果您尝试使用此代码:

echo "${str//<*>/|}"

然后会打印出来:

My work|build

答案 1 :(得分:1)

这不是一个答案,而是为了演示为什么不建议对这种HTML编辑使用模式匹配。我尝试了以下几点。

shopt -s extglob
set +H    # Turn off history expansion, if necessary, to allow the !(...) pattern
echo ${str//+(<+(!(>))>)/|}

首先:即使对于像str='My work</u><br />bob<foo>build'这样的简单字符串,它也不起作用。其次,对于原始问题中的字符串,它似乎锁定了shell;我怀疑这种复杂的模式会引发指数回溯。

以下是它的工作方式:

  1. !(>)是除>
  2. 之外的任何内容
  3. +(!(>))是一个或多个非>字符。
  4. <+(!(>))>><
  5. 中包含的一个或多个非>字符
  6. +(<+(!(>))>)是一组或多组<...> - 附上的非>
  7. 我的理论是,由于!(>)可以匹配多字符字符串以及单个字符,因此需要 ton 回溯。