【问题标题】:Extract surrounding words in python from a string position从字符串位置提取python中的周围单词
【发布时间】:2015-07-18 07:43:46
【问题描述】:

假设,我有一个字符串:

string="""<p>It is common for content in Arabic, Hebrew, and other languages that use right-to-left scripts to include numerals or include text from  other scripts. Both of these typically flow  left-to-right within the overall right-to-left  context. </p> <p>This article tells you how to write HTML where text with different writing directions is mixed <em>within a paragraph or other HTML block</em> (ie. <dfn id="term_inline">inline or phrasal</dfn> content). (A companion article <a href="/International/questions/qa-html-dir"><cite>Structural markup and right-to-left text in HTML</cite></a> tells you how to use HTML markup for  elements such as <code class="kw">html</code>, and structural markup such as <code class="kw">p</code> or <code class="kw">div</code> and forms.)</p>"""

我在这个字符串中有一个单词的位置,例如:

>>> pos = [m.start() for m in re.finditer("tells you", string)]
>>> pos
[263, 588]

我需要从每个位置提取后面的几个单词和后面的几个单词。 如何使用 Python 和正则表达式来实现?

例如:

def look_through(d, s):
    r = []
    content = readFile(d["path"])
    content = BeautifulSoup(content)
    content = content.getText()
    pos = [m.start() for m in re.finditer(s, content)]
    if pos:
        if "phrase" not in d:
            d["phrase"] = [s]
        else:
            d["phrase"].append(s)
        for p in pos:
            r.append({"content": content, "phrase": d["phrase"], "name": d["name"]})
    for b in d["decendent"] or []:
            r += look_through(b, s)
    return r

>>> dict = {
    "content": """<p>It is common for content in Arabic, Hebrew, and other languages that use right-to-left scripts to include numerals or include text from  other scripts. Both of these typically flow  left-to-right within the overall right-to-left  context. </p>""", 
    "name": "directory", 
    "decendent": [
         {
            "content": """<p>This article tells you how to write HTML where text with different writing directions is mixed <em>within a paragraph or other HTML block</em> (ie. <dfn id="term_inline">inline or phrasal</dfn> content). (A companion article <a href="/International/questions/qa-html-dir"><cite>Structural markup and right-to-left text in HTML</cite></a> tells you how to use HTML markup for  elements such as <code class="kw">html</code>, and structural markup such as <code class="kw">p</code> or <code class="kw">div</code> and forms.)</p>""", 
            "name": "subdirectory", 
            "decendent": None
        }, 
        {
            "content": """It tells you how to use HTML markup for  elements such as <code class="kw">html</code>, and structural markup such as <code class="kw">p</code> or <code class="kw">div</code> and forms.)""", 
            "name": "subdirectory_two", 
            "decendent": [
                {
                    "content": "Name 4", 
                    "name": "subsubdirectory", 
                    "decendent": None
                }
            ]
        }
    ]
}

所以:

>>> look_through(dict, "tells you")
[
    { "content": "This article tells you how to", "phrase": "tells you", "name": "subdirectory" },
    { "content": "It tells you how to use", "phrase": "tells you", "name": "subdirectory_two" }
]

谢谢!

【问题讨论】:

  • 你能在你的问题中添加一个小例子吗?
  • 你试过写这段代码吗?当我们可以看到您已经尝试过的方法或您正在考虑如何解决问题时,您可能会得到更好的响应。
  • 仍然不清楚你是如何得到"This article tells you how to"
  • 我想@Kasra 和我都很好奇您为实现look_through 所做的尝试。
  • @amccormack,我添加了一个如何获取文本位置的示例。现在我想从内容中提取文本的一部分,确切地找到它。我在这里看到了两种解决方案:使用位置或使用正则表达式。

标签: python regex string search


【解决方案1】:

你想要你的正则表达式命中的“一致性”,让我们在你的正则表达式匹配的地方之前和之后说两个词。最简单的方法是在此处断开您的字符串并将您的搜索锚定到片段的端点。例如,要在索引 263 之前和之后获取两个单词(您的第一个 m.start()),您可以:

m_left = re.search(r"(?:\s+\S+){,2}\s+\S*$", text[:263])
m_right = re.search(r"^\S*\s+(?:\S+\s+){2,}", text[263:])
print(text[m_left.start():m_right.end()])

第一个表达式应该从字符串的末尾向后读取:它锚定在末尾$,如果匹配在单词中间结束,可能会跳过部分单词,(\S*),跳过一些空格(@ 987654325@),然后匹配最多两个{2,}字空间序列\s+\S+。这不是完全两个,因为如果我们到达字符串的开头,我们想要返回一个短匹配。

第二个正则表达式的作用相同,但方向相反。

对于索引,您可能希望在正则表达式匹配的 end 之后立即开始阅读,而不是开始。在这种情况下,使用m.end() 作为第二个字符串的开头。

我认为如何将其与正则表达式匹配列表一起使用是很明显的。

【讨论】:

    【解决方案2】:

    我首先建议使用单词边界元字符,但这并不完全正确,因为它们不消耗任何字符串,而且 \B 无论如何都与我想要的不匹配。

    相反,我建议使用单词边界的基本定义——即\W 和\w 之间的边界。在搜索子字符串的任一侧以正确的顺序查找一个或多个单词字符 (\w) 以及一个或多个非单词字符 (\W),重复任意多次。

    例如: (?:\w+\W+){,3}some string(?:\W+\w+){,3}

    这会在“some string”之前找到最多三个单词,在“some string”之后最多找到三个单词。

    【讨论】:

    • 请参阅this,了解如何处理包含撇号的单词,例如“Don't”或“Haven't”。
    • 边界不占用空间。 \b\B 匹配一个是单词边界而不是单词边界的点,所以它永远不会匹配到任何地方。
    • @alexis,是的,这就是我继续回答的原因。
    • 当符号不是英文(在我的情况下是西里尔文)时,请考虑大小写。
    • @paus,您可以使用 UNICODE 或 LOCALE 标志来修改 \w 和 \W 的定义。查看文档:docs.python.org/2/library/re.html
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-11-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多