将直引号转换为引号的想法

时间:2009-02-04 00:57:08

标签: algorithm language-agnostic typography

我有一个包含“直”(普通,ASCII)引号的文件,我正在尝试将它们转换为真实quotation mark glyphs(“卷曲”引号,U + 2018到U + 201D)。由于从两个不同的引号字符转换为单个字符首先是有损的,显然没有办法自动执行这种转换;尽管如此,我怀疑一些启发式方法将涵盖大多数情况。因此,该计划是一个脚本(在Emacs中),它执行以下操作:对于每个直引号字符,

  1. 猜猜使用哪个卷曲引号字符,如果可能的话
  2. 要求用户(我)确认或做出选择
  3. 这个问题是关于第一步:对于普通的英文文本(例如小说),使用什么样的好算法(一组启发式,更像是)?以下是一些初步想法,我认为这些想法适用于双引号(反例是受欢迎的!):

    1. 如果双引号位于一行的开头,则猜测它是一个开头的引用。
    2. 如果双引号位于一行末尾,请猜一个结束语。
    3. 如果双引号前面有空格,请猜一个开头报价。
    4. 如果双引号后面跟一个空格,请猜一个收盘价。
    5. 如果双引号不符合上述类别之一,请猜测它是最近使用的双引号的“反面”。
    6. 单引号比较复杂,因为'可能是开头引号,结束引号,撇号,我们想要单独留下撇号(不能写“mustn” T”)。一些与上述相同的规则适用,但'可能的撇号是在单词(或行)的开头,尽管它不像过去的'twas那样常见。我不能随便想到能够正确处理像[“我喜欢'那'70年代表演'”这样的片段的规则,她说。它可能需要查看不仅仅是相邻字符,并计算引号之间的距离,例如......

      还有什么想法吗?如果不是所有可能的案件都包括在内,那也没关系;我们的目标是尽可能地聪明,但不能再进一步。 : - )

      修改:还有一些值得思考的事情(或者可能不相关,不确定):

      • 引号可能并不总是匹配对:对于单引号,显而易见的原因如上所述。但即使对于双引号,如果有一个引用延伸多个段落,通常的排版约定(不要问我为什么)是用引号开始每个段落,即使它在之前没有被关闭一。所以简单地保持一个在两个状态之间交替的状态机将工作!
      • 嵌套引用(在上面的“我喜欢'那个70年代的节目'”中提到:这可能会使任何一种引用而不是在空格之前或之后。
      • 英国/美国标点符号样式:引号内或外部是逗号吗?
      • 许多文字处理程序(例如Microsoft Word)已经进行了某种类似的转换。虽然它们并不完美并且经常令人讨厌,但了解它们如何工作可能是有益的......

9 个答案:

答案 0 :(得分:3)

一个好的起点是使用状态机:

  • 从位置0开始,遍历字符
  • 找到报价后,输入“报价”状态(公开报价)
  • 如果处于“Quoted”状态且您遇到报价,请返回“Starting”状态(收盘报价)

您可以在每个状态转换中做出其他决定。

例如,您可以尝试通过识别已知连词来标准化单引号,并在处理之前将它们转换为其他字符,而不是文本字符。

我的$ 0.02

答案 1 :(得分:2)

  

猜测要使用哪个卷曲引号字符

在一般情况下,它不是。

大多数自动转换器使用的简单算法只是查看您在'或'之前键入的前一个字母。如果是空格,行首,开括号或其他开头报价,请选择开头报价,否则关闭。这种方法的优点是它可以按你自己的方式运行,因此当它选择错误的方法时,你通常可以纠正它。

  

我们想单独留下撇号

我同意!但没有多少人这样做。将撇号转换为左向单引号是正常的排版实践。我个人更喜欢将它们保留原样,以区别于引号,使文本更容易(我发现)阅读,并且可以自动处理。

然而,这实际上只是我的口味而且通常不被认为是合理的,因为该字符被Unicode标准定义为APOSTROPHE。

  

'可能的撇号是在单词的开头

事实上。在没有大量文化背景的经典Fish'n'Chips等案例中,没有办法告诉撇号一个潜在的公开引用。

(更不用说素数,okinas,声门停止和撇号的各种其他用途......)

当然,最好的办法是安装一个可以直接输入智能引号的键盘布局。我有'AltGr + [],“”在AltGr + Shift + []上, - 在AltGr + [Shift] +破折号上,依此类推。

答案 2 :(得分:2)

看起来你的初始帖子涵盖了我将要写的大部分想法,这就是我留下的......

对于撇号示例(“我喜欢'那'70年代表'',她说,”引号不太可能直接嵌套在相同类型的引号内。你可以利用它。

在我看来,最好的方法是让代码只处理明确的情况(双引号非常简单)。对于具有多种可能选择的那些,将它们的位置存储在列表中并在完成时检查它。您可能会在那里找到一些更容易编码的案例,或者您可能只是决定手动修复它们。

答案 3 :(得分:1)

  1. 基本的事情是总是试图找到匹配的对。鉴于每个报价都有匹配的报价,只有在不确定哪个是匹配的报价的情况下,您才可以让您的计划寻求帮助。

  2. 打开引号始终位于一行的开头,或者前面有的空格。在之后,关闭引号总是一个空格。如果您发现带有以下引号的冒号,则可能是收尾报价。

  3. 如果报价后面的字母是大写的,那么它可能是一个开头的报价。

  4. 如果报价前面有标点符号,则可能是收盘价。

  5. 尝试迭代执行。该程序应首先询问您可以明确分配给函数的所有引号。 (只是为了确保它没有出现任何错误。)

  6. 在第二轮中,所有引号都不确定它们是在打开引号还是撇号。对于所有开盘报价,它必须自动找到收盘价。

  7. 另一个,也许不那么复杂的想法可能是:

    1. 查询所有非报价,向用户询问可能是报价或非报价的每一个。

    2. 所有剩余的引号应该相当容易转换。开盘报价在它们前面有一个空格或换行符,并在它们之后关闭。

    3. 最后一个想法:

      你应该分开这个过程,就像只处理段落一样。如果你的程序出错了,它可能会给出语言的复杂性,你就可以更容易地纠正它,并且程序可以从新段开始。

答案 4 :(得分:1)

我不想这么说,但最好的做法可能是研究Word的作用,然后复制它。即使在某些情况下它是错误的,它代表了许多人已经习以为常的标准。要模拟的一种行为是,在替换弯曲后,撤消(Ctrl-Z)会立即恢复为直引号。

答案 5 :(得分:1)

这是一个可能有助于双引号的正则表达式:

/([^\s\(]?)"(\s*)([^\\]*?(\\.[^\\]*)*)(\s*)("|\n\n)([^\s\)\.\,;]?)/gms

它将在每个段落重新启动,它将识别引号对(并且还允许您在引号之前和之后检查间距是否正确,如果这有用)。

Numbered element    identification  
  1               non-white-space before quote quote  
  2               white-space after leading quote  
  5               white-space before trailing quote  
  6               trailing quote (or double-newline, i.e. start of a paragraph  
  7               character after trailing quote if not whitespace or right   paren                     

我认为将其扩展到其他情况是合理的(我还没有必要。)

这是javascript语法。这是非常快的,但我还没有比我的“足够好”做更多的优化。它会在大约一秒钟内完成一本400页的书。我认为在程序上很难匹配它的速度。

答案 6 :(得分:1)

Computational linguistics有人吗?

有人提到,如果你有大量的文化背景,那可能是可行的。因此,针对该问题的过度但最准确的自动解决方案是shallow parsing。这需要您正在处理的任何语言和模式的语料库(例如the Brown corpus一般英语)。

根据语料库中出现的卷曲引号的句法上下文,为卷曲引号开发分类器。最后,给你的任意句法上下文直接引用你的分类器,然后弹出最可能的引号字符!

答案 7 :(得分:0)

[“我喜欢那'70年代表演',”她说]

我原本以为可能在文本上使用多次传递来获取上下文洞察力可能有所帮助,但这并不能解决所有实例。

你可以做的最好的事情是运行一个可能的单词集/表达式列表,如'twas,'tis,'70's等等,并将它们放入字典中并对其进行自动校正,将直道转换为卷发和反之亦然。无论如何,拼写检查都会运行在每个单词上吗? (抱歉,这对您的emacs问题没有帮助)

OO忽略了我所能说出的所有曲目的单引号。

Wikipedia对这些讨厌的事情有一些信息。

答案 8 :(得分:0)

尝试Shift + Ctrl +" (双引号键),这对我在Windows 10上工作,使用一个名为Kalipso的程序。