我正在使用 LaTeX 以编程方式生成 PDF。我知道我可以,\DeclareUnicodeCharacter
但当你有一个文件时,这才有效。我正在尝试从网上抓取的数据库中的内容生成 PDF。
我宁愿 PDF 中包含一些混乱的字符,也不愿我的用户在尝试生成 PDF 时遇到错误。
我如何强制 LaTeX 直接丢弃未知字符?由于我处理的是抓取的内容,所以这些字符大多是错误出现的。
我见过这个问题但提问者实际上希望输出中出现这些字符。我不希望。我不在乎每个文档是否缺少几个字符。我只想让 LaTeX 丢弃这些字符。
出于兼容性原因,我使用 pdflatex,所以我想避免使用 xetex 或 luatex,因为更改渲染引擎可能需要我们重新测试所有文档。
最小错误示例:
\documentclass[a4paper]{article}
\usepackage[utf8]{inputenx}
\usepackage[croatian]{babel}
\begin{document}
Sometimes crawler gets letters that look the same
but throw errors, like: O or о (Cyrillic)
instead of Latin O or o
\end{document}
在这个例子中,我可能可以告诉 babel 这是西里尔文本并且它会起作用,但我无法预先知道爬虫程序会拾取什么疯狂的字符。
另外:另一个选择是获取 pdflatex 知道如何处理的所有字符的列表,然后我将以编程方式丢弃所有其他字符。
答案1
您可以重新定义错误消息:
\documentclass[a4paper]{article}
\usepackage[croatian]{babel}
\makeatletter
\def\UTFviii@undefined@err#1{??UPS??}
\makeatother
\begin{document}
Sometimes crawler gets letters that look the same
but throw errors, like: O or о (cyrillic)
instead of latin O or o
\end{document}
自 2018 年起,utf8 为默认编码,因此加载inputenc
或inputenx
不需要,但无妨。如果inputenc
在文档中加载,则必须是 loader前重新定义错误消息,以便它不会再次覆盖消息。
答案2
我会使用 Ulrike 的答案,但要回答您的问题,您可以从中获取基本 LaTeX 发行版已知的 Unicode 代码点列表
/usr/local/texlive/2022/texmf-dist/tex/latex/base/utf8enc.dfu
kpsewhich utf8enc.dfu
(或者你的系统上提供的任何路径)
答案3
基本上,感谢@David Carlisle的回答,我成功地提取了LaTeX的所有Unicode代码知道如何打印,并且我在 ruby 中创建了一个简单的函数,它只保留字符串中的这些字符,同时用字符替换所有其他字符?
。
### not the prettiest code in the world but it works for me.
### First we remove all the invalid utf8 characters, then we remove
### all unprintable characters, and then we remove all the characters
### that LaTeX does not know how to render.
def utf8_tex(txt)
begin
out = txt&.chars&.select(&:valid_encoding?)&.join
out2 = out&.gsub(/[^[:print:]]/,'')
rescue
puts "fail on remove invalid"
end
tex_valid = [160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171,
172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183,
184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195,
196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207,
208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219,
220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231,
232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243,
244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255,
256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267,
268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279,
280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291,
292, 293, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305,
306, 307, 308, 309, 310, 311, 313, 314, 315, 316, 317, 318,
321, 322, 323, 324, 325, 326, 327, 328, 330, 331, 332, 333,
334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345,
346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357,
360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371,
372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 402,
461, 462, 463, 464, 465, 466, 467, 468, 482, 483, 486, 487,
488, 489, 490, 491, 496, 500, 501, 536, 537, 538, 539, 562,
563, 567, 710, 711, 732, 728, 729, 731, 733, 1024, 1025, 1026,
1027, 1028, 1029, 1030, 1031, 1032, 1033, 1034, 1035, 1036,
1037, 1038, 1039, 1040, 1041, 1042, 1043, 1044, 1045, 1046,
1047, 1048, 1049, 1050, 1051, 1052, 1053, 1054, 1055, 1056,
1057, 1058, 1059, 1060, 1061, 1062, 1063, 1064, 1065, 1066,
1067, 1068, 1069, 1070, 1071, 1072, 1073, 1074, 1075, 1076,
1077, 1078, 1079, 1080, 1081, 1082, 1083, 1084, 1085, 1086,
1087, 1088, 1089, 1090, 1091, 1092, 1093, 1094, 1095, 1096,
1097, 1098, 1099, 1100, 1101, 1102, 1103, 1104, 1105, 1106,
1107, 1108, 1109, 1110, 1111, 1112, 1113, 1114, 1115, 1116,
1117, 1118, 1119, 1122, 1123, 1130, 1131, 1138, 1139, 1140,
1141, 1142, 1143, 1164, 1165, 1166, 1167, 1168, 1169, 1170,
1171, 1172, 1173, 1174, 1175, 1176, 1177, 1178, 1179, 1180,
1181, 1182, 1183, 1184, 1185, 1186, 1187, 1188, 1189, 1190,
1191, 1192, 1193, 1194, 1195, 1196, 1197, 1198, 1199, 1200,
1201, 1202, 1203, 1204, 1205, 1206, 1207, 1208, 1209, 1210,
1211, 1212, 1213, 1214, 1215, 1216, 1217, 1218, 1219, 1220,
1221, 1222, 1223, 1224, 1227, 1228, 1229, 1230, 1232, 1233,
1234, 1235, 1236, 1237, 1238, 1239, 1240, 1241, 1242, 1243,
1244, 1245, 1246, 1247, 1248, 1249, 1250, 1251, 1252, 1253,
1254, 1255, 1256, 1257, 1260, 1261, 1262, 1263, 1264, 1265,
1266, 1267, 1268, 1269, 1270, 1271, 1272, 1273, 1274, 1275,
1276, 1277, 1278, 1279, 3647, 7682, 7683, 7838, 8204, 8208,
8209, 8210, 8211, 8212, 8213, 8214, 8216, 8217, 8218, 8220,
8221, 8222, 8224, 8225, 8226, 8230, 8240, 8241, 8249, 8250,
8251, 8253, 8260, 8270, 8274, 8353, 8356, 8358, 8361, 8363,
8364, 8369, 8451, 8470, 8471, 8478, 8480, 8482, 8486, 8487,
8494, 8592, 8593, 8594, 8595, 9001, 9002, 9250, 9251, 9702,
9711, 9834, 10216, 10217, 7712, 7713, 64256, 64257, 64258,
64259, 64260, 64261, 64262, 65279]
clean = out2.unpack('U*').map{|x| (x<160 or tex_valid.include?(x)) ? x : 63}.pack('U*')
end
功劳应归功劳:打包/解包
答案4
将您抓取的数据通过一个过滤器,该过滤器会删除所有行为不当的 Unicode 字符。例如,使用正则表达式搜索并替换所有与允许集不匹配的字符,并将其替换为空字符串。
一个可能的例子,在 PERL 中:
perl -CSD -pe "s/[^\p{ASCII}]//gu"
这只是一个例子,您可能希望更改正则表达式以包含您实际使用的所有字符(如 Levara 的答案中所示)。您可能还想先执行字符集转换。