¿Importan las preguntas? (III) (making of)

Tenía dudas sobre sí explicar los detalles técnicos del análisis anterior. Por una parte es un aspecto de interés restringido. Por otra parte se utilizan comandos de muy venerable antigüedad. Pero, finalmente, son comandos y formas de pensar desconocidas en muchos currículos españoles al uso que se han adaptado a la ofimática de bolsillo y al uso compulsivo del pequeño roedor.

He necesitado un intérprete de comandos (bien servido de comandos) y un fichero (proporcionado gentilmente por El País) que contiene la transcripción de la declaración en formato plano (código ASCII-UTF8 sin pasar por programas tipo word o algo por el estilo) y en el que, afortunadamente, cada intervención es una línea. Esto es importante porque los comandos de edición en flujo actúan, comúnmente, línea a línea. Además, como señale en la primera entrada, cada interviniente se identifica por una etiqueta (tag) único. Así el juez de la causa aparece etiquetado como JUEZ y Cristina Federica como CF. Ambas cosas, cada intervención es una línea, y cada intervención está etiquetada según quién es el interviniente, hace posible el análisis que hice.

El primer comando que uso es cat que sirve para mostrar o concatenar archivos. Ahora lo usaré para mostrar, al final lo usaré para concatenar:

cat nombre_del_archivo

Realmente el listado no tiene porqué volcarse en pantalla para verse; puede dirigirse por una tubería (es un símil pero es el símil que se usa: igual que el agua fluye por una tubería el contenido del archivo fluye por otra). En esa tubería el contenido del archivo va a ser filtrado y procesado. Primero con un grep:

cat nombre_del_archivo | grep JUEZ -A 1

El carácter | es el que marca que el contenido del archivo va por una tubería donde lo captura grep. La instrucción grep busca expresiones regulares (entre ellas la búsqueda simple de la palabra que aparezca a continuación) y saca fuera de la tubería todas aquellas líneas que no contengan el primer argumento que, en este caso es la palabra JUEZ. Es decir, por la tubería sigue fluyendo aquellas líneas que contienen la palabra JUEZ: sus intervenciones. Con la opción -A[fter] 1, además, se deja seguir por la tubería la línea siguiente a cada una de las líneas donde apareció JUEZ. Ahora por la tubería fluye las palabras de JUEZ y la intervención siguiente. Algo como esto:


<p><strong>JUEZ:</strong> Folio dos mil quinientos y pico. Sabe usted de qué texto forman parte esos párrafos que se le han leído? Con los que estaba de acuerdo, sabe de qué texto más amplio forman parte?</p>
<p><strong>CF:</strong> No, estaba de acuerdo con la parte que estaba señalaba.</p>
<p><strong>JUEZ:</strong> Forman parte de un auto que se dictó próximo a dos años, pronto, el mes que viene hará dos años de ese acto, es obvio que usted estaba conforme, porque desestimaba una petición que se había cursado para que usted fuera citada a declarar en calidad de imputada. Un año después aproximadamente recayó otro auto, en el que se le citaba a usted, que luego no llegó a prosperar. Leyó alguna parte de ese auto, que no llegó a prosperar, porque fue revocado o suspendido por la Audiencia Provincial?</p>
<p><strong>CF:</strong> No lo leí en su integridad, pero mis abogados han...</p>

Ahora filtro las intervenciones de CF usando de nuevo grep y las enumero usando la opción -b de cat:

cat nombre_del_archivo | grep JUEZ -A 1 | grep CF | cat -b

Tendré entonces el conjunto enumerado de intervenciones de CF a preguntas de JUEZ. Also así como:


1 <p><strong>CF:</strong> Sí, lo sé.</p>
2 <p><strong>CF:</strong> Sí, sé cuáles son.</p>
3 <p><strong>CF:</strong> Voy a prestar declaración Señoría.</p>
4 <p><strong>CF:</strong> Muchas gracias.</p>
5 <p><strong>CF:</strong> Señoría, no lo recuerdo bien, pero bastantes.</p>
.
.
.
675 <p><strong>CF:</strong> Al estar al 50%, me imagino que algo sí, pero no tengo más conocimientos.</p>
676 <p><strong>CF:</strong> Si me permite, no voy a responder a ninguna acusación popular.</p>
677 <p><strong>CF:</strong> Sí.</p>
678 <p><strong>CF:</strong> No, estaba de acuerdo con la parte que estaba señalaba.</p>
679 <p><strong>CF:</strong> No lo leí en su integridad, pero mis abogados han...</p>
680 <p><strong>CF:</strong> He leído varios párrafos y mis abogados</p>
681 <p><strong>CF:</strong> No le puedo precisar ahora con qué párrafos puedo estar de acuerdo y cuáles no Señoría.</p>

Obviamente la numeración de las respuestas de CF coincide con la numeración de preguntas de JUEZ.

Ahora un poco de limpieza con sed (stream editor, o editor de flujo) que lo voy a usar simplemente para buscar-sustituir en el flujo (es capaz de muchísimo más; su ventaja, frente a otros buscar-sustituir radica en que es programable). Primero filtro y elimino las etiquetas html que contiene el archivo y después elimino los signos de puntuación más comunes, la coma y el punto. La sintaxis básica es sed s/"qué quiero encontrar"/"con qué lo sustituyo"/g. Así:

cat nombre_del_archivo | grep JUEZ -A 1 | grep CF | cat -b | sed 's/<[^>]\+>//g' | sed 's/[,.]/ /g'

La primera de las llamadas de sed elimina las etiquetas html. Si no entienden lo que ponen no se preocupen: sed es uno de los comandos que produce líneas de código más ininteligibles y contraintuitivas. En parte el código no se entiende porque usa patrón de búsqueda de expresiones regulares y no una búsqueda simple. Explicado con un ejemplo: no quiero encontrar «p» (una etiqueta html) y eliminarlo (sustituirlo por nada) quiero encontrar cualquier etiqueta html. Afortunadamente estas etiquetas son regulares: un signo « más varios caracteres más otro signo ». Así el comando de búsqueda hace: encontrar < y todos los siguientes caracteres salvo > “[^>]” (el ^ marca la excepción) que se aparezcan varias veces (+) hasta terminar en >. Es decir <whatever>. Y sustituye todo eso por un espacio en blanco para facilitar posteriormente la búsqueda.

La segunda es más simple. Busca puntos o comas y los elimina (sustituir por nada). El resultado es:


1 CF: Sí lo sé
2 CF: Sí sé cuáles son
3 CF: Voy a prestar declaración Señoría
4 CF: Muchas gracias
5 CF: Señoría no lo recuerdo bien pero bastantes
.
.
.
675 CF: Al estar al 50% me imagino que algo sí pero no tengo más conocimientos
676 CF: Si me permite no voy a responder a ninguna acusación popular
677 CF: Sí
678 CF: No estaba de acuerdo con la parte que estaba señalaba
679 CF: No lo leí en su integridad pero mis abogados han
680 CF: He leído varios párrafos y mis abogados
681 CF: No le puedo precisar ahora con qué párrafos puedo estar de acuerdo y cuáles no Señoría

Finalmente se usa el comando grep otra vez para encontrar la partícula no. Ahora lo uso con comillas para asegurame de que está aislada (espacio antes y después; por ello quité los puntos anteriormente) y no en medio (coNOcimiento), al final (balonmaNO) o al principio (NOvela) de una palabra:

cat nombre_del_archivo | grep JUEZ -A 1 | grep CF | cat -b |sed 's/<[^>]\+>/ /g' | sed 's/[,.]//g' |grep -i [-v] " no "

La opción -i hace la búsqueda insensible a si es mayúscula o minúscula y la opción -v, si está presente, haría una búsqueda inversa: en vez de encontrar cuándo aparece ” no ” encontraría cuándo no aparece ” no “. El resultado sería algo así como:


5 CF: Señoría no lo recuerdo bien pero bastantes
.
.
.
675 CF: Al estar al 50% me imagino que algo sí pero no tengo más conocimientos
676 CF: Si me permite no voy a responder a ninguna acusación popular
678 CF: No estaba de acuerdo con la parte que estaba señalaba
679 CF: No lo leí en su integridad pero mis abogados han
681 CF: No le puedo precisar ahora con qué párrafos puedo estar de acuerdo y cuáles no Señoría

donde de debe observarse que algunas respuestas, por ejemplo la primera, segunda o la 680º no aparecen ya que en ella no se encuentra la partícula negativa ” no “.

Como no me interesa el contenido de la respuesta filtro el resultado y me quedo únicamente con la primera parte del contenido gracias al utilísimo comando awk:

cat nombre_del_archivo | grep JUEZ -A 1 | grep CF | cat -b | sed 's/<[^>]\+>/ /g' | sed 's/[,.]//g' |grep -i [-v] " no " | awk '{print $1}'

que dejaría el resultado en algo así como:


5
11
.
.
.
675
676
678
679
681

Finalmente vuelco (con >) el contenido de la tubería en una botella, para conservar el resultado. Esa botella es un archivo que contiene el ordinal de las respuestas de CF a JUEZ que contienen la palabra ” no “. En otro archivo se guarda las que no contienen ” no “.

cat nombre_del_archivo | grep JUEZ -A 1 | grep CF | cat -b|sed 's/<[^>]+>/ /g' | sed 's/,.//g' |grep -i [-v] " no " | awk '{print $1}' > nombre_archivo_salida

Ahora tengo un fichero que me dice, por ejemplo que la quinta respuesta de CF y la 675ª y la 676ª fueron negativas. Es decir, que la primera respuesta negativa de CF fue a la quinta pregunta de JUEZ. La segunda respuesta negativa fue la respuesta a la undécima pregunta de JUEZ y así sucesivamente. De forma que puedo hacer las gráficas que aperecieron en la primera entrada.

Simplemente variando el orden de los comandos puedo buscar las intervenciones de JUEZ que son preguntas a CF y no diálogos con otras de las partes del interrogatorio:

cat nombre_del_archivo | grep CF -B 1 | grep JUEZ |cat -b

Ahora se busca primero CF y la línea anterior -B[efore] 1 para despúes buscar JUEZ. El resto sería igual.

Finalmente puedo interseccionar conjuntos de la siguiente forma:

cat preguntas_JUEZ_si respuestas_CF_no

concatena por la tubería el ordinal de las preguntas del JUEZ que no contienen ” no ” y las respuestas de CF que sí contienen ” no “. Con el comando sort se ordena la tubería un con el comando uniq -d se retiene aquellas ocurrencias que aparecen en los dos archivos:

cat preguntas_JUEZ_si respuestas_CF_no | sort -n |uniq -d > fichero_salida

Es decir el conjunto de preguntas/respuesta que satisface un criterio dado. Variando los parámetros de los ficheros de entrada se pueden realizar las gráficas comparativas que aparecieron en la entrada anterior.

Anuncios

7 comentarios en “¿Importan las preguntas? (III) (making of)

  1. Me ha encantado.

    Siempre termino por crearme una shell script que invariablemente contiene un cat fichero |while read line do…done, uno o varios bloques if .. fi y un montón de variables.

    En una línea queda tan aseadito!!

  2. Sí, lo he visto.

    El artículo es un truño.
    El enlace primero está bien. Se ve que no se enteró de nada.

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s