【问题标题】:Convert quotation marks to Latex format with Python使用 Python 将引号转换为 Latex 格式
【发布时间】:2017-06-08 19:38:07
【问题描述】:

tl;dr 版本

我的段落可能包含引号(例如“blah blah”、“this one also”等)。现在我必须在 python 3.0 的帮助下将它替换为乳胶风格的引用(例如“blah blah”、“this also”等)。

背景

我有很多纯文本文件(超过 100 个)。现在,在对这些文件进行少量文本处理后,我必须制作一个包含从这些文件中获取的内容的单个 Latex 文档。为此,我正在使用 Python 3.0。现在我可以让其他所有内容(如转义字符、部分等)工作,但我无法正确获取引号。

我可以找到带有正则表达式的模式(如here 所述),但是如何用给定的模式替换它?在这种情况下,我不知道如何使用“re.sub()”函数。因为我的字符串中可能有多个引号实例。有this 与此相关的问题,但是我如何用python 实现呢?

【问题讨论】:

    标签: python regex python-3.x latex


    【解决方案1】:

    设计注意事项

    1. 我只考虑了常规的"double-quotes"'single-quotes'。可能还有其他引号(见this question
    2. LaTeX 结束引号也是单引号 - 我们不想捕获 LaTeX 双引号(例如“LaTeX 双引号”)并将其误认为是单引号(几乎没有)李>
    3. 单词缩写和所有权's 包含单引号(例如don'tJohn's)。它们的特点是字母字符围绕在引号的两侧
    4. 常规名词(复数所有权)在单词后有单引号(例如 the actresses' roles

    解决方案

    import re
    
    def texify_single_quote(in_string):
        in_string = ' ' + in_string #Hack (see explanations)
        return re.sub(r"(?<=\s)'(?!')(.*?)'", r"`\1'", in_string)[1:]
    
    def texify_double_quote(in_string):
        return re.sub(r'"(.*?)"', r"``\1''", in_string)
    

    测试

    with open("test.txt", 'r') as fd_in, open("output.txt", 'w') as fd_out:
        for line in fd_in.readlines():
    
            #Test for commutativity
            assert texify_single_quote(texify_double_quote(in_string)) == texify_double_quote(texify_single_quote(in_string))
    
            line = texify_single_quote(line)
            line = texify_double_quote(line)
            fd_out.write(line)
    

    输入文件(test.txt):

    # 'single', 'single', "double"
    # 'single', "double", 'single'
    # "double", 'single', 'single'
    # "double", "double", 'single'
    # "double", 'single', "double"
    # I'm a 'single' person
    # I'm a "double" person?
    # Ownership for plural words; the peoples' 'rights'
    # John's dog barked 'Woof!', and Fred's parents' 'loving' cat ran away.
    # "A double-quoted phrase, with a 'single' quote inside"
    # 'A single-quoted phrase with a "double quote" inside, with contracted words such as "don't"'
    # 'A single-quoted phrase with a regular noun such as actresses' roles'
    

    输出(output.txt):

    # `single', `single', ``double''
    # `single', ``double'', `single'
    # ``double'', `single', `single'
    # ``double'', ``double'', `single'
    # ``double'', `single', ``double''
    # I'm a `single' person
    # I'm a ``double'' person?
    # Ownership for plural words; the peoples' `rights'
    # John's dog barked `Woof!', and Fred's parents' `loving' cat ran away.
    # ``A double-quoted phrase, with a `single' quote inside''
    # `A single-quoted phrase with a ``double quote'' inside, with contracted words such as ``don't'''
    # `A single-quoted phrase with a regular noun such as actresses' roles'
    

    注意 cmets 被预先添加以停止对帖子输出进行格式化!

    说明

    我们将分解这个正则表达式模式,(?&lt;=\s)'(?!')(.*?)'

    • 总结(?&lt;=\s)'(?!') 处理开头的单引号,而(.*?) 处理引号中的内容。
    • (?&lt;=\s)'positive look-behind 并且只匹配前面有空格 (\s) 的单引号。这对于防止匹配缩略词(例如 can't)非常重要(注意事项 3、4)。
    • '(?!')negative look-ahead,仅匹配 not 后跟另一个单引号的单引号(注意事项 2)。
    • this answer 中所述,(.*?) 模式捕获引号之间的内容,而\1 包含捕获内容。
    • "Hack" in_string = ' ' + in_string 之所以存在,是因为正向后视 捕获从行首开始的单引号,因此为所有行(然后在返回时用切片删除它,return re.sub(...)[1:])解决了这个问题!

    【讨论】:

    • 谢谢你这么好的解释,但是单引号函数 (texify_single_quote) 不起作用。 ://
    • 别担心!你能告诉我它是怎么不工作的吗?似乎在我的系统上工作得很好。
    • 啊,我明白了,我想可能是当我们有一个这样的字符串时:(这是我的“测试”字符串,这是一个“双重”)。可能是“test”之后的单引号 ' 和“double”之后的单引号正在匹配。抱歉,我必须阅读更多关于 Regex 的内容才能找到答案——我会尽快回复您。附:使用括号,因为我无法在所有这些引号中格式化代码块!
    • 无论如何,谢谢。为您的努力 +1 :)
    • 嗯,所以我在一个文本文件上进行了尝试(请参阅编辑),如果您只在双过滤器之前使用单过滤器,事情似乎工作正常 - 不确定这是否可以(但会继续研究更“稳健”的解决方案)
    【解决方案2】:

    正则表达式非常适合某些任务,但它们仍然有限(阅读this 了解更多信息)。为此任务编写解析器似乎更容易出错。

    我为此任务创建了一个简单的函数并添加了 cmets。如果对实施仍有疑问,请询问。

    代码(online version here):

    the_text = '''
    This is my \"test\" String
    This is my \'test\' String
    This is my 'test' String
    This is my \"test\" String which has \"two\" quotes
    This is my \'test\' String which has \'two\' quotes
    This is my \'test\' String which has \"two\" quotes
    This is my \"test\" String which has \'two\' quotes
    '''
    
    
    def convert_quotes(txt, quote_type):
        # find all quotes
        quotes_pos = []
        idx = -1
    
        while True:
            idx = txt.find(quote_type, idx+1)
            if idx == -1:
                break
            quotes_pos.append(idx)
    
        if len(quotes_pos) % 2 == 1:
            raise ValueError('bad number of quotes of type %s' % quote_type)
    
        # replace quote with ``
        new_txt = []
        last_pos = -1
    
        for i, pos in enumerate(quotes_pos):
            # ignore the odd quotes - we dont replace them
            if i % 2 == 1:
                continue
            new_txt += txt[last_pos+1:pos]
            new_txt += '``'
            last_pos = pos
    
        # append the last part of the string
        new_txt += txt[last_pos+1:]
    
        return ''.join(new_txt)
    
    print(convert_quotes(convert_quotes(the_text, '\''), '"'))
    

    打印出来:

    This is my ``test" String
    This is my ``test' String
    This is my ``test' String
    This is my ``test" String which has ``two" quotes
    This is my ``test' String which has ``two' quotes
    This is my ``test' String which has ``two" quotes
    This is my ``test" String which has ``two' quotes
    

    注意:解析嵌套引号是不明确的。

    例如: 字符串"bob said: "alice said: hello"" 嵌套在正确的语言上

    但是:

    字符串"bob said: hi" and "alice said: hello" 没有嵌套。

    如果这是您的情况,您可能希望首先将这些嵌套引号解析为不同的引号,或使用括号 () 进行嵌套引号消歧。

    【讨论】:

    • 有趣的方法!
    猜你喜欢
    • 2022-11-14
    • 2010-09-25
    • 1970-01-01
    • 1970-01-01
    • 2013-11-09
    • 2022-01-21
    • 2018-05-19
    • 1970-01-01
    相关资源
    最近更新 更多