Tengo un archivo de texto persa que tiene algunas líneas como esta:
ذوب 6 خوی 7 بزاق ،آبدهان ، یم 10 زهاب، 11 آبرو، حیثیت، شرف
Quiero generar una lista de palabras de esta línea. Para mí, los bordes de las palabras son números, como 6, 7, etc. en la línea anterior y también el carácter. por lo que la lista debe ser:
[ 'ذوب','خوی','بزاق','آبدهان','یم','زهاب','آبرو','حیثیت' ,'شرف']
Quiero hacer esto en Python 3.3. Cuál es la mejor manera de hacer esto, realmente aprecio cualquier ayuda en esto.
EDITAR:
Obtuve varias respuestas, pero cuando las usé para otro caso de prueba no funcionaron. El caso de prueba es este:
منهدم کردن : 1 خراب کردن، ویران کردن، تخریب کردن 2 نابود کردن، از بین بردن
y espero tener una lista de tokens como esto:
['منهدم کردن','خراب کردن', 'ویران کردن', 'تخریب کردن','نابود کردن', 'از بین بردن']
Usando el paquete regex
:
>>> import regex >>> text = 'ذوب 6 خوی 7 بزاق ،آبدهان ، یم 10 زهاب، 11 آبرو، حیثیت، شرف' >>> regex.findall(r'\p{L}+', text.replace('\u200c', '')) ['ذوب', 'خوی', 'بزاق', 'آبدهان', 'یم', 'زهاب', 'آبرو', 'حیثیت', 'شرف']
str.replace
. \p{L}
o \p{Letter}
coincide con cualquier tipo de letra de cualquier idioma. Ver el tutorial de Regex – Caracteres y propiedades de Unicode .
ACTUALIZAR
Para incluir también U + 200C, use [\p{Cf}\p{L}]+
lugar ( \p{Cf}
o \p{Format}
coincide con el carácter de formato invisible):
>>> regex.findall(r'[\p{Cf}\p{L}]+', text) ['ذوب', 'خوی', 'بزاق', 'آب\u200cدهان', 'یم', 'زهاب', 'آبرو', 'حیثیت', 'شرف']
Se ve diferente de lo que quieres, pero son iguales:
>>> got = regex.findall(r'[\p{Cf}\p{L}]+', text) >>> want = [ 'ذوب','خوی','بزاق','آبدهان','یم','زهاب','آبرو','حیثیت' ,'شرف'] >>> print(want) ['ذوب', 'خوی', 'بزاق', 'آب\u200cدهان', 'یم', 'زهاب', 'آبرو', 'حیثیت', 'شرف'] >>> got == want >>> got[:3] ['ذوب', 'خوی', 'بزاق'] >>> got[4:] ['یم', 'زهاب', 'آبرو', 'حیثیت', 'شرف']
Actualización2
Algunas palabras en la pregunta editada contienen un espacio.
>>> ' ' in 'منهدم کردن' True
Agregué \s
en el siguiente código para que coincida también con los espacios, luego elimine los espacios iniciales y finales de las cadenas coincidentes, luego filtre las cadenas vacías.
>>> text = 'منهدم کردن : 1 خراب کردن، ویران کردن، تخریب کردن 2 نابود کردن، از بین بردن' >>> want = ['منهدم کردن','خراب کردن', 'ویران کردن', 'تخریب کردن','نابود کردن', 'از بین بردن'] >>> [x for x in map(str.strip, regex.findall(r'[\p{Cf}\p{L}\s]+', text)) if x] == want True
Use re.split
para dividir en espacios en blanco ( \s
), dígitos ( \d
) y el carácter ،
.
# python 3 import re INPUT = 'ذوب 6 خوی 7 بزاق ،آبدهان ، یم 10 زهاب، 11 آبرو، حیثیت، شرف' EXPECTED = [ 'ذوب','خوی','بزاق','آبدهان','یم','زهاب','آبرو','حیثیت' ,'شرف'] OUTPUT = re.split('[\s\d،]+', INPUT) assert OUTPUT == EXPECTED print('\n'.join(OUTPUT))
Tenga en cuenta que el \u200c
que está viendo en la matriz de salida es un carácter que no se puede imprimir y en realidad está contenido en la cadena original. Python se está escapando porque muestra la representación de la matriz y las cadenas contenidas, no imprime la cadena para mostrarla. Aquí está la diferencia:
INPUT = 'ذوب 6 خوی 7 بزاق ،آبدهان ، یم 10 زهاب، 11 آبرو، حیثیت، شرف' print(INPUT) ذوب 6 خوی 7 بزاق ،آبدهان ، یم 10 زهاب، 11 آبرو، حیثیت، شرف print(repr(INPUT)) # notice the \u200c below 'ذوب 6 خوی 7 بزاق ،آب\u200cدهان ، یم 10 زهاب، 11 آبرو، حیثیت، شرف' print(['in', 'an', 'array', INPUT]) # the \u200c is also shown when printing an array ['in', 'an', 'array', 'ذوب 6 خوی 7 بزاق ،آب\u200cدهان ، یم 10 زهاب، 11 آبرو، حیثیت، شرف']
Esto es similar a cómo Python maneja los caracteres de newline
:
>>> 'new\nline' 'new\nline' >>> print 'new\nline' new line
Editar:
Aquí está la expresión regular para su muestra actualizada que usa la estrategia findall de falsetru, pero usa el módulo de re
incorporado:
OUTPUT = [s.strip() for s in re.findall(r'(?:[^\W\d_]|[\s])+', INPUT) if s.strip()]
El patrón (?:[^\W\d_]|[\s])+
es un poco extraño, ya que el módulo re de Python no tiene equivalente a las “Letras” \p{L}
regex, así que en su lugar usamos la solución propuesta aquí https://stackoverflow.com/a/8923988/66349
[^\W\d_] - (not ((not alphanumeric) or digits or underscore))
Entonces, en resumen, haga coincidir uno o más caracteres ( +
) que sean ( |
): letras Unicode [^\W\d_
, o espacios en blanco \s
.
El método de falsetru es probablemente más legible, pero requiere la biblioteca de terceros.