如何将除标签外的普通引号转换为吉列梅特(法语引号)

时间:2019-04-07 07:50:47

标签: python regex typography

假设我们有以下文字:

<a href="link">some link</a> How to transform "ordinary quotes" to «Guillemets»

需要的是将其转换为

<a href="link">some link</a> How to transform «ordinary quotes» to «Guillemets»

使用正则表达式和Python。

我尝试过

import re

content = '<a href="link">some link</a> How to transform "ordinary quotes" to «Guillemets»'

res = re.sub('(?:"([^>]*)")(?!>)', '«\g<1>»', content)

print(res)

但是,正如@WiktorStribiżew注意到的那样,如果一个或多个标签将具有多个属性,则此方法将无效,因此

<a href="link" target="_blank">some link</a> How to transform "ordinary quotes" to «Guillemets»

将转换为

<a href=«link" target=»_blank">some link</a> How to transform «ordinary quotes» to «Guillemets»

更新

请注意文字

  • 可以是html,即:

<div><a href="link" target="_blank">some link</a> How to transform "ordinary quotes" to «Guillemets»</div>

  • 不能是html,即:

How to transform "ordinary quotes" to «Guillemets»

  • 不能是html,但要包含一些html标签,即

<a href="link" target="_blank">some link</a> How to transform "ordinary quotes" to «Guillemets»

3 个答案:

答案 0 :(得分:0)

当您拿着锤子时,一切看起来都像钉子。您不必使用正则表达式。一个简单的状态机就可以做到(假设<>中的任何内容都是HTML标记)。

public function duoAuthentication()
{
    $username = $input['email'];
    $sig_request = Web::signRequest($ikey, $skey, $akey, $username);
    return view('users::duo', [
        'host' => "api-5ccb0890.duosecurity.com",
        'sig_request' => $sig_request,
        'post_action' => '/user/redirect/to/dashboard',
        'user_id' => $usercheck['id'],
    ]);
}

说明:

# pos - current position in a string
# q1,q2 - opening and closing quotes position
s = ' How to transform "ordinary quotes" to «Guillemets» and " more <div><a href="link" target="_blank">some "bad" link</a>'
sl = list(s)
q1, q2 = 0, 0
pos = 0
while 1:
    tag_open = s.find('<', pos)
    q1 = s.find('"', pos)
    if q1 < 0:
        break   # no more quotation marks
    elif tag_open >= 0 and q1 > tag_open:
        pos = s.find('>', tag_open)     # tag close
    elif (tag_open >= 0 and q1 < tag_open) or tag_open < 0:
        q2 = s.find('"', q1 + 1)
        if q2 > 0 and (tag_open < 0 or q2 < tag_open):
            sl[q1] = '«'
            sl[q2] = '»'
            s = ''.join(sl)
            pos = q2
        else:
            pos = q1 + 1
print(s)

答案 1 :(得分:-1)

这对我有用:

res = re.sub('(?:"([^>]*)")(?!>)', '«\g<1>»', content)

从文档中

  

除了如上所述的字符转义和反向引用   上面的\ g将使用与名为name的组匹配的子字符串,如   由(?P ...)语法定义。 \ g使用​​相应的组号;   因此,\ g <2>等效于\ 2,但在   替换,例如\ g <2> 0。 \ 20将被解释为对   第20组,而不是对第2组的引用,后跟文字字符   '0'。后向引用\ g <0>替换整个子字符串   与RE相匹配。

答案 2 :(得分:-1)

您愿意分三遍这样做吗:[a]换掉HTML内的引号; [b]将剩余的报价换成吉尔; [c]恢复HTML内的引号吗?

请记住,先行抱怨是昂贵的,然后再抱怨它的速度。

[a] first = re.sub(r'<.*?>', lambda x: re.sub(r'"', '', x.group(0)), content)
[b] second = re.sub(r'"(.*?)"', r'«\1»', first)
[c] third = re.sub(r'', '"', second)

关于路易的评论:

first = re.sub(r'<.*?>', lambda x: re.sub(r'"', 'WILLSWAPSOON', x.group(0)), content)

有些场景可以使用上述策略。也许OP正在其中之一内工作。否则,如果这些麻烦太多了,OP可以转到BeautifulSoup并开始使用它...