python - script - Convertir pinyin numerado a pinyin con marcas de tono
python shell commands (5)
¿Existen scripts, bibliotecas o programas que utilicen Python
o herramientas BASH
(por ejemplo, awk
, perl
, sed
) que puedan convertir correctamente pinyin numerados (por ejemplo, dian4 nao3) a pinyin UTF-8 con marcas de tono (por ejemplo, diàn nǎo)?
He encontrado los siguientes ejemplos, pero requieren PHP
o #C
:
- Convertir PHP numerado a acentuado Pinyin?
C ¿ Alguna biblioteca para convertir el número Pinyin a Pinyin con marcas de tono?
También he encontrado varias herramientas en línea, pero no pueden manejar un gran número de conversiones.
Encontré una macro VBA que lo hace en Microsoft Word, en pinyinjoe.com
Tenía un defecto menor que informé y él respondió que él incorporaría mi sugerencia "tan pronto como pueda" Eso fue a principios de enero de 2014; No he tenido ninguna motivación para verificar, ya que ya está en mi copia.
Escribí otra función de Python que hace esto, que no distingue entre mayúsculas y minúsculas y preserva los espacios, la puntuación y otros textos (a menos que haya falsos positivos, por supuesto):
# -*- coding: utf-8 -*-
import re
pinyinToneMarks = {
u''a'': u''āáǎà'', u''e'': u''ēéěè'', u''i'': u''īíǐì'',
u''o'': u''ōóǒò'', u''u'': u''ūúǔù'', u''ü'': u''ǖǘǚǜ'',
u''A'': u''ĀÁǍÀ'', u''E'': u''ĒÉĚÈ'', u''I'': u''ĪÍǏÌ'',
u''O'': u''ŌÓǑÒ'', u''U'': u''ŪÚǓÙ'', u''Ü'': u''ǕǗǙǛ''
}
def convertPinyinCallback(m):
tone=int(m.group(3))%5
r=m.group(1).replace(u''v'', u''ü'').replace(u''V'', u''Ü'')
# for multple vowels, use first one if it is a/e/o, otherwise use second one
pos=0
if len(r)>1 and not r[0] in ''aeoAEO'':
pos=1
if tone != 0:
r=r[0:pos]+pinyinToneMarks[r[pos]][tone-1]+r[pos+1:]
return r+m.group(2)
def convertPinyin(s):
return re.sub(ur''([aeiouüvÜ]{1,3})(n?g?r?)([012345])'', convertPinyinCallback, s, flags=re.IGNORECASE)
print convertPinyin(u''Ni3 hao3 ma0?'')
La biblioteca cjklib cubre sus necesidades:
O use el shell de Python:
>>> from cjklib.reading import ReadingFactory
>>> f = ReadingFactory()
>>> print f.convert(''Bei3jing1'', ''Pinyin'', ''Pinyin'', sourceOptions={''toneMarkType'': ''numbers''})
Běijīng
O simplemente la línea de comando:
$ cjknife -m Bei3jing1
Běijīng
Descargo de responsabilidad: he desarrollado esa biblioteca.
Porté el código de dani_l a Kotlin (el código en java debería ser bastante similar). Va :
import java.util.regex.Pattern
val pinyinToneMarks = mapOf(
''a'' to "āáǎà",
''e'' to "ēéěè",
''i'' to "īíǐì",
''o'' to "ōóǒò",
''u'' to "ūúǔù",
''ü'' to "ǖǘǚǜ",
''A'' to "ĀÁǍÀ",
''E'' to "ĒÉĚÈ",
''I'' to "ĪÍǏÌ",
''O'' to "ŌÓǑÒ",
''U'' to "ŪÚǓÙ",
''Ü'' to "ǕǗǙǛ"
)
fun toPinyin(asciiPinyin: String) :String {
val pattern = Pattern.compile("([aeiouüvÜ]{1,3})(n?g?r?)([012345])")!!
val matcher = pattern.matcher(asciiPinyin)
val s = StringBuilder()
var start = 0
while (matcher.find(start)) {
s.append(asciiPinyin, start, matcher.start(1))
val tone = Integer.parseInt(matcher.group(3)!!) % 5
val r = matcher.group(1)!!.replace("v", "ü").replace("V", "Ü")
// for multple vowels, use first one if it is a/e/o, otherwise use second one
val pos = if (r.length >1 && r[0].toString() !in "aeoAEO") 1 else 0
if (tone != 0) s.append(r, 0, pos).append(pinyinToneMarks[r[pos]]!![tone - 1]).append(r, pos + 1, r.length)
else s.append(r)
s.append(matcher.group(2))
start = matcher.end(3)
}
if (start != asciiPinyin.length) s.append(asciiPinyin, start, asciiPinyin.length)
return s.toString()
}
fun test() = print(toPinyin("Ni3 hao3 ma0?"))
Tengo un código de Python 3 que hace esto, y es lo suficientemente pequeño como para poner directamente la respuesta aquí.
PinyinToneMark = {
0: "aoeiuv/u00fc",
1: "/u0101/u014d/u0113/u012b/u016b/u01d6/u01d6",
2: "/u00e1/u00f3/u00e9/u00ed/u00fa/u01d8/u01d8",
3: "/u01ce/u01d2/u011b/u01d0/u01d4/u01da/u01da",
4: "/u00e0/u00f2/u00e8/u00ec/u00f9/u01dc/u01dc",
}
def decode_pinyin(s):
s = s.lower()
r = ""
t = ""
for c in s:
if c >= ''a'' and c <= ''z'':
t += c
elif c == '':'':
assert t[-1] == ''u''
t = t[:-1] + "/u00fc"
else:
if c >= ''0'' and c <= ''5'':
tone = int(c) % 5
if tone != 0:
m = re.search("[aoeiuv/u00fc]+", t)
if m is None:
t += c
elif len(m.group(0)) == 1:
t = t[:m.start(0)] + PinyinToneMark[tone][PinyinToneMark[0].index(m.group(0))] + t[m.end(0):]
else:
if ''a'' in t:
t = t.replace("a", PinyinToneMark[tone][0])
elif ''o'' in t:
t = t.replace("o", PinyinToneMark[tone][1])
elif ''e'' in t:
t = t.replace("e", PinyinToneMark[tone][2])
elif t.endswith("ui"):
t = t.replace("i", PinyinToneMark[tone][3])
elif t.endswith("iu"):
t = t.replace("u", PinyinToneMark[tone][4])
else:
t += "!"
r += t
t = ""
r += t
return r
Esto maneja ü
, u:
y v
, todos los cuales he encontrado. Se necesitarán modificaciones menores para la compatibilidad con Python 2.