将“直引号”转换为“弯引号”

23

我有一个应用程序,它使用基于Javascript的规则引擎。我需要一种方法将常规的直引号转换为卷曲(或智能)引号。可以使用 string.replace 替换 ["] 来实现,但这只会插入一个卷曲引号。

我能想到的最好方法是将第一个引号替换为左卷曲引号,之后每个引号都替换为左卷曲引号,而剩余的引号替换为右卷曲引号。

是否有一种用Javascript实现这个目标的方法?


1
你可能想要尝试一下文字处理器,并查看它使用哪些规则来确定使用哪些引号。从我所见,它们是基于引用的上下文而不是配对关系。 - Nate C-K
这个回答解决了你的问题吗?将直引号转换为弯引号的想法 - Dave Jarvis
7个回答

15

你可以用左引号替换所有紧跟着一个单词字符之前的内容,用右引号替换所有跟在一个单词字符之后的内容。

str = str.replace(/"(?=\w|$)/g, "“");
str = str.replace(/(?<=\w|^)"/g, "&#8221;"); // IF the language supports look-
                                             // behind. Otherwise, see below.

正如下面的评论所指出的那样,这并没有考虑标点符号,但很容易实现:

/(?<=[\w,.?!\)]|^)"/g

[编辑:] 对于不支持反向查找的语言(例如Javascript),只要首先替换所有正向查找,您有两个选择:

str = str.replace(/"/g, "&#8221;"); // Replace the rest with right curly quotes
// or...
str = str.replace(/\b"/g, "&#8221;"); // Replace any quotes after a word
                                      // boundary with right curly quotes

(如果有人使用支持向后查找的语言,我已经在上面保留了原始解决方案,以便他们参考)


+1 针对问题的实际回答。但是,使用者应该考虑到它并不在每种情况下都完美无缺 - 例如,表示英尺和英寸的破折号。 - Anon.
@BlueVoid - 你关于错误是正确的,我在你评论时发现了这个问题并正在更新我的答案 :) 谨慎处理你的代码 - ?= 是一个前瞻,它之所以匹配是因为它向前查看并看到引号,而引号在你的字符类中。我建议采用我编辑后答案中的第一个“替代”解决方案 - 在替换花括号后,将所有花括号都替换为花括号。 - Nicole
@Renesis 说得好。这样简化了事情。它运行得很好。 - BlueVoid
@Renesis,@BlueVoid:这个正则表达式似乎对于一般用途来说太过脆弱了,因为你必须要考虑到以“逻辑引用”结尾的句子。它只适用于像这样的对话:“Jimmy 说,“妈妈,我们到了吗?””。请查看经济学人以了解我所指的内容;他们的风格指南中的这篇文章解释了你在这里忽略的内容。我不知道你将如何处理“单引号”,更不用说撇号了。 - tchrist
@tchrist 在80%或90%的解决方案和100%的解决方案之间,开发时间有很大的差异。这里重要的部分不是\w,而是使用一个正则表达式来处理前导引号和另一个正则表达式来处理尾随引号的策略。它将正确编码大多数情况([编辑]后的第一个建议将解决您提出的问题),一个错误的情况不会破坏其他情况,并且可以轻松编辑以涵盖更多情况。例如,您可以反转它以基于另一侧的空格触发。或者,您可以将标点符号添加到字符类中。 - Nicole
显示剩余2条评论

5

您可能想看看Pandoc的功能-显然使用--smart选项,它可以在所有情况下(包括例如“'tis”和“'twere”)正确处理引号。

我最近编写了一个JavaScript排版美化引擎,其中包括引号替换。我最终使用了Renesis建议的算法,但目前还有一个失败的测试正在等待更智能的解决方案。

如果您有兴趣借鉴我的代码(和/或提交基于您所做工作的补丁),请查看:jsPrettifyjsprettify.prettifyStr可以实现您要求的功能。如果您不想处理Closure依赖关系,则有一个旧版本可以独立运行-它甚至可以在Rhino中运行。


为 Pandoc 点赞。每当我可以使用成熟且经过测试的工具时,我都会尽量避免自己编写正则表达式。手工编写的正则表达式可能会过于贪婪或者不够贪婪,并且可能无法准确处理单词边界和逗号等情况。而 Pandoc 就考虑了大多数这些情况以及更多其他情况。 - Paulb

4
'foo "foo bar" "bar"'.replace(/"([-a-zA-Z0-9 ]+)"/g, function(wholeMatch, m1){
    return "“" + m1 + "”";
});

1
这并没有回答问题。 - SLaks
1
它将如何处理“John was 6' 4"”? - Anon.
1
@Anon,如果程序不够聪明,不知道英寸和英尺是什么,它该如何处理呢? - Earlz
2
通常情况下,我看到的东西会正确地用花括号包含引号,但是也会用同样的方式将英寸标记弯曲。它没有弯曲英寸标记,然后将每个其他引号标记都与它应该做的相反方式弯曲。 - Anon.
1
@Anon:那么也许你应该发布一个解决方案。 - Luca Matteis
显示剩余3条评论

3
以下代码会将每个引号都交替更改(但此特定示例将略过孤立的引号)。
str.replace(/\"([^\"]*)\"/gi,"&#8220;$1&#8221;");

只要您要排版的文本没有因为双引号的不当使用而出现错误,这个功能就能完美工作。在英语中,引号从不嵌套。


4
在英语中有一种情况下,这个规则会被打破。当你有连续的代表同一发言者的引用段落时,每个段落必须以适当的引号开始(单引号、双引号、单引号+双引号、双引号+单引号等),但是除了最后一个段落外,同一发言者的其他段落都不需要加结尾引号。 - tchrist

0

我在这里没有找到我想要的逻辑,所以这就是我最终选择的方案。

value = value.replace(/(^|\s)(")/g, "$1“"); // replace quotes that start a line or follow spaces
value = value.replace(/"/g, "”"); // replace rest of quotes with the back smart quote

我有一个小文本框,需要将直引号替换为卷引号(智能引号)。 我只是在键盘按键事件时执行此逻辑。 我试图使它的行为类似于Microsoft Word。


0

我认为像这样的一般情况并不容易,因为您必须准确解释内容中每个双引号字符的含义。话虽如此,我会收集所有我感兴趣的文本节点,然后逐个跟踪每个双引号实例的“开/关”(或“奇/偶”;任何)性质。然后您就可以知道要使用哪个替换实体。


0

为了记录下来,我发了这篇文章。

根据@Steven Dee的建议,我去了Pandoc

每当可能时,我都会尽量使用成熟和经过测试的工具,而不是自己编写正则表达式。手动编写的正则表达式可能会过于贪婪或者不够贪婪,也可能对单词边界和逗号等不敏感。Pandoc 能够解决大部分问题。

从命令行(--smart参数打开智能引号):

pandoc --smart --standalone -o output.html input.html

我知道命令行脚本可能不符合OP使用JavaScript的要求。(相关:如何在JavaScript中执行shell命令


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接