当我从包含以下内容的 Adobe Reader PDF 文件复制时
Define an operation
我更愿意看到
Dene an operation
当我粘贴文本时,为什么会出现这种情况?
我怎样才能解决这个恼人的问题呢?
当我用打印机打印 Microsoft Office Word 文件时,我也遇到过这种情况。
答案1
这听起来像是字体问题。PDF 可能使用 OpenTypefi
结扎在单词中define
,并且目标应用程序的当前字体缺少该字形。
我不知道是否有一种简单的方法可以让 Acrobat 分解复制的连字符。
您的打印问题可能也与字体有关。某些原因可能允许打印机用其内置字体替换文档的字体,而打印机版本的字体也缺少该特定字形。您必须告诉 Windows 始终将字体下载到打印机才能解决此问题。
打印时的另一种可能性:UniScribe 可能未启用。 微软知识库 2642020讨论了这个问题以及一些可能的解决方法(即使用 RAW 类型打印而不是 EMF 类型打印)。虽然上下文与您的具体问题略有不同,但原因可能相同,并且可能适用相同的解决方法。
答案2
这里的问题是,其他答案注释,带有连字。然而,这与 OpenType 毫无关系。根本问题是 PDF 是一种预印格式,它很少关注内容和语义,而是致力于忠实地呈现打印出来的页面。
文本不是以文本形式布局,而是以字形字体的某些位置。因此,你会得到类似这样的信息:“将字形编号 72 放在那里,将字形编号 101 放在那里,将字形编号 108 放在那里,...”。在这个层面上,从根本上来说,没有文本的概念根本. 这只是描述如何看起来从一堆字形中提取含义有两个问题:
空间布局。由于 PDF 已经包含了每个字形的具体位置信息,因此它下面没有实际的文本,这很正常。另一个副作用是没有空格。当然,如果你看文本的话,你会发现有空格,但 PDF 中没有。为什么要发出一个空白的字形,而你可以根本不发出任何字形呢?毕竟结果是一样的。因此,PDF 阅读器必须小心地将文本重新拼凑起来,每当遇到字形之间的较大间隙时就插入一个空格。
PDF 渲染的是字形,而不是文本。大多数情况下,字形 ID 与嵌入字体中的 Unicode 代码点或至少 ASCII 代码相对应,这意味着您通常可以很好地恢复 ASCII 或 Latin 1 文本,具体取决于最初创建 PDF 的人(一些乱码一切过程中)。但通常,即使是允许你顺利输出 ASCII 文本的 PDF 也会损坏所有内容。不是ASCII。对于包含以下内容的复杂文字(例如阿拉伯文)尤其糟糕仅有的布局阶段之后的连字和替代字形,这意味着阿拉伯语 PDF 几乎从不包含实际文本
第二个问题和您遇到的问题类似。这里常见的罪魁祸首是 LaTeX,它使用估计有 238982375 种不同的字体(每种字体限制为 256 个字形)来实现其输出。普通文本、数学(使用多种字体)等的不同字体使事情变得非常困难,尤其是 Metafont 比 Unicode 早了近二十年,因此从未有过 Unicode 映射。变音符号也由字母上叠加的分音符呈现,例如,从 PDF 复制时,您会得到 »¨a« 而不是 »ä«(当然也无法搜索它)。
生成 PDF 的应用程序可以选择将实际文本作为元数据包含在内。如果不这样做,您就只能听天由命,看看嵌入字体的处理方式以及 PDF 阅读器是否可以将原始文本重新拼凑起来。但是,如果 »fi« 被复制为空白或根本没有复制,通常是 LaTeX PDF 的标志。您应该将 Unicode 字符画在石头上,然后扔给制作者,希望他们会改用 XeLaTeX,从而最终迎来字符编码和字体标准的 90 年代。
答案3
您可以用原始单词替换大部分“损坏”的单词。如果符合以下条件,则可以安全地替换单词:
- 像
dene
或rey
,这不是一个真正的词 - 类似
define
或firefly
,有一重新添加连字符序列(ff
,fi
,fl
,ffi
或ffl
)并形成真实单词的方法
大多数连字符问题都符合这些标准。但是,您不能替换:
us
因为它是一个真实的词,尽管它最初可能是fluffs
- 还
affirm
,butterfly
,fielders
,fortifies
,flimflam
,misfits
...
- 还
cus
因为它可能会cuffs
变成ficus
- 还
stiffed
/stifled
,rifle
/riffle
,flung
/fluffing
...
- 还
在这本收录 49.6 万词的英语词典, 有16055包含至少一个ff
、fi
、fl
、ffi
或 的单词ffl
,可转换为15879单词的连字符被删除后。173那些缺失的单词像cuffs
和一样碰撞ficus
,最后3是因为该词典包含单词ff
、fi
和fl
。
790这些“去掉连字符”的单词都是真实单词,例如us
,但是15089都是破碎的话语。14960被破坏的单词可以安全地用原来的单词替换,这意味着99.1%破碎的词语是可以修复的,93.2%复制粘贴 PDF 后,可以恢复包含连字符的原始单词。6.8%包含连字序列的单词会因碰撞(cus
)和子词(us
)而丢失,除非您选择某种方式(单词/文档上下文?)为每个没有保证替换的单词选择最佳替换。
下面是生成上述统计数据的 Python 脚本。它需要一个每行一个单词的字典文本文件。最后,它会写入一个 CSV 文件,将可修复的破损单词映射到其原始单词。
以下是下载 CSV 的链接: http://www.filedropper.com/brokenligaturewordfixes 将此映射与正则表达式替换脚本之类的东西结合起来,以便替换大多数损坏的单词。
import csv
import itertools
import operator
import re
dictionary_file_path = 'dictionary.txt'
broken_word_fixes_file_path = 'broken_word_fixes.csv'
ligatures = 'ffi', 'ffl', 'ff', 'fi', 'fl'
with open(dictionary_file_path, 'r') as dictionary_file:
dictionary_words = list(set(line.strip()
for line in dictionary_file.readlines()))
broken_word_fixes = {}
ligature_words = set()
ligature_removed_words = set()
broken_words = set()
multi_ligature_words = set()
# Find broken word fixes for words with one ligature sequence
# Example: "dene" --> "define"
words_and_ligatures = list(itertools.product(dictionary_words, ligatures))
for i, (word, ligature) in enumerate(words_and_ligatures):
if i % 50000 == 0:
print('1-ligature words {percent:.3g}% complete'
.format(percent=100 * i / len(words_and_ligatures)))
for ligature_match in re.finditer(ligature, word):
if word in ligature_words:
multi_ligature_words.add(word)
ligature_words.add(word)
if word == ligature:
break
# Skip words that contain a larger ligature
if (('ffi' in word and ligature != 'ffi') or
('ffl' in word and ligature != 'ffl')):
break
# Replace ligatures with dots to avoid creating new ligatures
# Example: "offline" --> "of.ine" to avoid creating "fi"
ligature_removed_word = (word[:ligature_match.start()] +
'.' +
word[ligature_match.end():])
# Skip words that contain another ligature
if any(ligature in ligature_removed_word for ligature in ligatures):
continue
ligature_removed_word = ligature_removed_word.replace('.', '')
ligature_removed_words.add(ligature_removed_word)
if ligature_removed_word not in dictionary_words:
broken_word = ligature_removed_word
broken_words.add(broken_word)
if broken_word not in broken_word_fixes:
broken_word_fixes[broken_word] = word
else:
# Ignore broken words with multiple possible fixes
# Example: "cus" --> "cuffs" or "ficus"
broken_word_fixes[broken_word] = None
# Find broken word fixes for word with multiple ligature sequences
# Example: "rey" --> "firefly"
multi_ligature_words = sorted(multi_ligature_words)
numbers_of_ligatures_in_word = 2, 3
for number_of_ligatures_in_word in numbers_of_ligatures_in_word:
ligature_lists = itertools.combinations_with_replacement(
ligatures, r=number_of_ligatures_in_word
)
words_and_ligature_lists = list(itertools.product(
multi_ligature_words, ligature_lists
))
for i, (word, ligature_list) in enumerate(words_and_ligature_lists):
if i % 1000 == 0:
print('{n}-ligature words {percent:.3g}% complete'
.format(n=number_of_ligatures_in_word,
percent=100 * i / len(words_and_ligature_lists)))
# Skip words that contain a larger ligature
if (('ffi' in word and 'ffi' not in ligature_list) or
('ffl' in word and 'ffl' not in ligature_list)):
continue
ligature_removed_word = word
for ligature in ligature_list:
ligature_matches = list(re.finditer(ligature, ligature_removed_word))
if not ligature_matches:
break
ligature_match = ligature_matches[0]
# Replace ligatures with dots to avoid creating new ligatures
# Example: "offline" --> "of.ine" to avoid creating "fi"
ligature_removed_word = (
ligature_removed_word[:ligature_match.start()] +
'.' +
ligature_removed_word[ligature_match.end():]
)
else:
# Skip words that contain another ligature
if any(ligature in ligature_removed_word for ligature in ligatures):
continue
ligature_removed_word = ligature_removed_word.replace('.', '')
ligature_removed_words.add(ligature_removed_word)
if ligature_removed_word not in dictionary_words:
broken_word = ligature_removed_word
broken_words.add(broken_word)
if broken_word not in broken_word_fixes:
broken_word_fixes[broken_word] = word
else:
# Ignore broken words with multiple possible fixes
# Example: "ung" --> "flung" or "fluffing"
broken_word_fixes[broken_word] = None
# Remove broken words with multiple possible fixes
for broken_word, fixed_word in broken_word_fixes.copy().items():
if not fixed_word:
broken_word_fixes.pop(broken_word)
number_of_ligature_words = len(ligature_words)
number_of_ligature_removed_words = len(ligature_removed_words)
number_of_broken_words = len(broken_words)
number_of_fixable_broken_words = len(
[word for word in set(broken_word_fixes.keys())
if word and broken_word_fixes[word]]
)
number_of_recoverable_ligature_words = len(
[word for word in set(broken_word_fixes.values())
if word]
)
print(number_of_ligature_words, 'ligature words')
print(number_of_ligature_removed_words, 'ligature-removed words')
print(number_of_broken_words, 'broken words')
print(number_of_fixable_broken_words,
'fixable broken words ({percent:.3g}% fixable)'
.format(percent=(
100 * number_of_fixable_broken_words / number_of_broken_words
)))
print(number_of_recoverable_ligature_words,
'recoverable ligature words ({percent:.3g}% recoverable)'
'(for at least one broken word)'
.format(percent=(
100 * number_of_recoverable_ligature_words / number_of_ligature_words
)))
with open(broken_word_fixes_file_path, 'w+', newline='') as broken_word_fixes_file:
csv_writer = csv.writer(broken_word_fixes_file)
sorted_broken_word_fixes = sorted(broken_word_fixes.items(),
key=operator.itemgetter(0))
for broken_word, fixed_word in sorted_broken_word_fixes:
csv_writer.writerow([broken_word, fixed_word])
答案4
如果您正在生成此 pdf,您可以首先阻止输入连字符。
我从 markdown 和 css 生成 pdf 并包含以下内容,以便我可以将我的文档转换为其他格式 - 包括 word - 而不会丢失 ff、fi、fl 等:
* {
font-variant-ligatures: none;
}