PDA

Ver la Versión Completa : Ejercicios de verano (primera letra en mayúsculas)


WillyWeb
25/06/18, 19:15:30
Me he encontrado en un foro (no digo cuál par no dar pistas) una cuestión aparentemente sencilla que está dando mucho juego.

La pregunta del millón es esta...

¿Cómo capitalizar la primera letra de cada palabra en una cadena separada por comas?

Esta cadena: grande,la,tengo,más,la,quisiera
La quiero así: Grande,La,Tengo,Más,La,Quisiera

La premisa es que sólo se deben usar acciones de Tasker (nada de JavaScript).

Los primeros intentos lo han conseguido con una tarea de 11 acciones, pero sospecho que se puede hacer con unas pocas menos. :pensando:

¿Algún valiente acepta el mini-reto? :silbando:

SmartPhoneLover
25/06/18, 20:11:40
Esto es lo que se me ha ocurrido... ;)

<-> Método 1>
A1: Anchor
A2: For [ Variable:%temp1 Items:grande,la tengo,más,la,quisiera ]
A3: Variable Convert [ Name:%temp1 Function:To Upper Case First Store Result In: ]
A4: Variable Set [ Name:%temp2 To:%temp1, Recurse Variables:Off Do Maths:Off Append:On ]
A5: End For
A6: Flash [ Text:%temp2 Long:On ]
<-> Método 2>
A7: Anchor
A8: Array Set [ Variable Array:%temp1 Values:grande,la tengo,más,la,quisiera Splitter:, ]
A9: Variable Set [ Name:%temp2 To:(%temp2)+1 Recurse Variables:Off Do Maths:On Append:Off ]
A10: Variable Convert [ Name:%temp1(%temp2) Function:To Upper Case First Store Result In:%temp3 ]
A11: Variable Set [ Name:%temp4 To:%temp3 Recurse Variables:Off Do Maths:Off Append:On ]
A12: Variable Set [ Name:%temp4 To:, Recurse Variables:Off Do Maths:Off Append:On ] If [ %temp2 !~ %temp1(#) ]
A13: Goto [ Type:Action Number Number:9 Label: ] If [ %temp2 !~ %temp1(#) ]
A14: Flash [ Text:%temp4 Long:On ]Se podrían mejorar de infinidad de maneras, pero os lo dejo a vuestra imaginación. :D

WillyWeb
26/06/18, 11:57:24
<-> Método 1>
A1: Anchor
A2: For [ Variable:%temp1 Items:grande,la tengo,más,la,quisiera ]
A3: Variable Convert [ Name:%temp1 Function:To Upper Case First Store Result In: ]
A4: Variable Set [ Name:%temp2 To:%temp1, Recurse Variables:Off Do Maths:Off Append:On ]
A5: End For
A6: Flash [ Text:%temp2 Long:On ]

Simple y elegante. :ok:

No lo he probado, pero juraría que al final saldrá una coma que no debería salir. :pensando:

<-> Método 2>
A7: Anchor
A8: Array Set [ Variable Array:%temp1 Values:grande,la tengo,más,la,quisiera Splitter:, ]
A9: Variable Set [ Name:%temp2 To:(%temp2)+1 Recurse Variables:Off Do Maths:On Append:Off ]
A10: Variable Convert [ Name:%temp1(%temp2) Function:To Upper Case First Store Result In:%temp3 ]
A11: Variable Set [ Name:%temp4 To:%temp3 Recurse Variables:Off Do Maths:Off Append:On ]
A12: Variable Set [ Name:%temp4 To:, Recurse Variables:Off Do Maths:Off Append:On ] If [ %temp2 !~ %temp1(#) ]
A13: Goto [ Type:Action Number Number:9 Label: ] If [ %temp2 !~ %temp1(#) ]
A14: Flash [ Text:%temp4 Long:On ]

Parece que con este sistema se resuelve el tema de la coma final, pero en A8 haces una cosa que puede tener resultados "inesperados". El nombre que usas como base para el array (%temp1) ya es un elemento de un array ¿...? El resultado de esa acción debería ser algo así...

de %temp1 a %temp10 sin definir
%temp11=grande
%temp12=la tengo << te falta una coma aquí
%temp13=más
%temp14=la
%temp15=quisiera

Yo diría que la tarea funcionará (tampoco la he probado), pero ¿era eso lo que querías hacer? :oh:

WillyWeb
26/06/18, 18:19:06
Aquí está mi propuesta con Tasker puro...

PrimeraLetraEnMayúsculas (666)
A1: Establecer variable [ Nombre:%org A:grande,la,tengo,más,la,quisiera Recurse Variables:Apagado Calcular:Apagado Añadir:Apagado ]
A2: Establece Array [ Matriz de Variables (array):%org Values:%org Separador:, ]
A3: For [ Variable:%ind Ítems:1:%org(#) ]
A4: Convertir Variable [ Nombre:%org(%ind) Función:A Mayúsculas Primero Almacenar Resultado en: ]
A5: End For
A6: Concatenar variable [ Nombre:%org Criterio de fusión:, Borrar partes:Encendido ]

La lista de palabras originales está en la variable %org y en esa misma variable queda el resultado. La cuestión inicial también tenía esa premisa. Perdón por no comentarlo antes. :rolleyes:

Luego me he puesto a pensar si esto se podía atacar con expresiones regulares ... :pensando:

Y sí que se puede. :ok:

Esto saca la primera letra de cada palabra que esté separada por un espacio en blanco o una coma...

(^|\s|,)[a-z]

Y esto convierte en mayúsculas cada coincidencia...

\U\0

Funciona perfectamente...

https://regex101.com/r/HpoJpg/2

Pero al intentar meterlo todo en una acción de "Buscar y Reemplazar" no consigo el resultado deseado, aunque me quedo muy cerca. :cry:

SmartPhoneLover
27/06/18, 19:08:29
Pero al intentar meterlo todo en una acción de "Buscar y Reemplazar" no consigo el resultado deseado, aunque me quedo muy cerca. :cry:

Lo tratas como un grupo de acciones separadas al uso de expresiones? O sea, qué quieres decir con "meter todo"?

WillyWeb
27/06/18, 20:25:25
Si miras en el enlace que puse antes creo que lo entenderás...

https://regex101.com/r/HpoJpg/2

Con esto ... (^|\s|,)[a-z] ... en REGULAR EXPRESSION y esto ... \U\0 ... en SUBSTITUTION el resultado es el esperado.

En la acción de Tasker pongo lo primero en el campo "Buscar" pero al poner lo segundo en el campo "Reemplazar Con" no consigo el resultado que esperaba. Parece que ese segundo campo no admite una expresión regular, o yo no encuentro la forma de ponerla de manera que Tasker la entienda.

SmartPhoneLover
27/06/18, 22:16:47
Y por qué no probar con sed...? ;-)

Se me ocurrió que podriamos hacer toda la operación en una única línea. Pero por ahora solo tengo la parte del código que se encarga de separar las palabras y agregar comas con espacios.

echo "%var" | sed 's/,/ /g'

Como comenté al principio, la parte del comando sed arriba expuesta, por ahora, lo único que hace es sustituir, en este caso, las comas por espacios. Por lo tanto, las palabras quedarían separadas. Pero por qué? Para qué?
Pues, estoy intentado dar con la combinación correcta para hacer que sed convierta la primer letra de cada palabra separada en mayúscula con '\U', pero no hay manera. (sé que es posible) Grrrrr

A ver si vosotros encontrais la forma :pensando:

Entonces, si lograsemos dar con la parte de las expresiones que faltan, la fórmula quedaria tal que así:

echo "%var" | sed 's/,/ /g; <expresiones_uppercase>; s/ /, /g;'


Notas:
- Quizás sea innecesaria la parte previa de eliminación de la coma por espacios, y se pueda omitir.
- Si llegase a funcionar, ni siquiera haría failta una acción previa para pasarle las palabras, sino que usando la variable '%par#' podriamos pasar todo directamente.

Caravantes
28/06/18, 21:06:50
Y por qué no probar con sed...? Se me ocurrió que podriamos hacer toda la operación en una única línea...

Google es mi amigo.
He encontrado una página en la que alguien pregunta lo mismo y recibe (entre otras) la siguiente respuesta que es más evolucionada de lo que buscábamos porque admite varias líneas y porque además pone a minúsculas cualquier posible mayúscula que no esté al inicio de palabra.

echo 'my string
ANOTHER STRING
tHiRd StRiNg' | sed -En '
y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/
:loop
h
s/^(.*[^a-zA-Z0-9])?([a-z]).*$/\2/
t next
b end
:next
y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/
G
s/^(.+)\n(.*[^a-zA-Z0-9])?[a-z](.*)$/\2\1\3/
t loop
:end
p
'

Output:
My String
Another String
Third String

Debajo de ese código, el tipo añade las explicaciones para entenderlo.
https://stackoverflow.com/questions/31968793/how-to-capitalize-first-letter-of-every-word-using-sed-in-osx

También he encontrado una página que es como una enciclopedia dedicada solo al comando SED: http://www.grymoire.com/Unix/Sed.html

Saludos.

SmartPhoneLover
28/06/18, 21:21:41
Madre mia. De usar acciones simples, hemos pasado a la complejidad extrema XD

Muchas gracias Caravantes!!! Muy útil! ;)


:dios:

WillyWeb
28/06/18, 21:48:28
La cuestión en ese post comienza con esto...

Estoy intentando capitalizar la primera letra de cada palabra con esta sentencia "sed" pero no funciona...

echo "my string" | sed 's/\b\(.\)/\u\1/g'

Resultado: my string

¿qué estoy haciendo mal?

Lo primero que me llama la atención es que esa "\u" no esté en mayúsculas. ¿Alguien puede verificar que eso está bien/mal?

WillyWeb
28/06/18, 21:54:23
Tengo la sospecha de que falla algo más ...

sed 's/\b\(.\)/\u\1/g'

... debería ser ...

sed 's/\b\(.\)/\U\0/g'

¿Alguien lo puede probar?

SmartPhoneLover
28/06/18, 21:54:40
Efectivamente, no funciona. Al menos a mi tampoco. Y si cambio la u por U, pasa lo mismo.
Quizás sea un argumento que no venga incluido, al menos, en las applets propias de Android. (he comprobado, y no veo por ningún lugar ningún argumento referente a modificar tamaño de letras)

GraphicAdventure
29/06/18, 22:38:52
Tasker usa regex flavor Java y una extensión de Perl 5.
Java no soporta \U y no permite modificar una variable directamente.
En el campo reemplazar solo se pueden usar referencias a grupos para alterar lo que la propia expresión contiene.

WillyWeb
30/06/18, 10:07:06
Java no soporta \U y no permite modificar una variable directamente.

Puede que Tasker no soporte el parámetro \U y está claro que "sed" no lo soporta, pero en Java sí parece que se puede usar ...

https://regex101.com/r/HpoJpg/2/codegen?language=java

Llegados a este punto parece que las tareas a base de acciones de Tasker y/o un pequeño script de JS (que el peticionario no quería usar) son las soluciones más viables. :pensando:

GraphicAdventure
30/06/18, 19:49:24
https://docs.oracle.com/javase/7/docs/api/java/util/regex/Pattern.html

Comparison to Perl 5
Perl constructs not supported by this class:
The preprocessing operations \l \u, \L, and \U.

Creo que el código generado por regex101 no está bien.
Si pasas el cursor por sustitución en \U pone: Custom regex101 property
Supongo que le habrán dado ese soporte.

Regex suele ser mi primera opción para muchas cosas pero no sirve para todo está claro.
Ya que Tasker tiene esta función, tampoco está mal hacer uso de ella.

WillyWeb
30/06/18, 20:22:40
Si pasas el cursor por sustitución en \U pone: Custom regex101 property

Cierto. Ese detalle se me había pasado. :rolleyes:

Está claro que esta vez regex no nos sacará del apuro. Las tareas con acciones de Tasker y el script para sed que dejó Caravantes son la solución a este asunto.

Gracias por los datos sobre el soporte regex de Tasker. :ok:

SmartPhoneLover
30/06/18, 20:28:36
Puede que Tasker no soporte el parámetro \U y está claro que "sed" no lo soporta, pero en Java sí parece que se puede usar ...

https://regex101.com/r/HpoJpg/2/codegen?language=java

Llegados a este punto parece que las tareas a base de acciones de Tasker y/o un pequeño script de JS (que el peticionario no quería usar) son las soluciones más viables. :pensando:

En efecto, Java lo icluye en sus librerias. Lo que no incluye es una predeterminada para capitalizar la primera letra de una palabra, pero vamos, no es nada dificil:

String temp1 = tasker;
temp2 = temp1.charAt(0);
temp3 = String(temp2);
%temp = temp3.toUpperCase();

Luego, continuas o con la función 'replaceFirst' o concatenate, or tiras de acciones de variables en Tasker para volver a juntar esa letra ya capitalizada al resto del cuerpo de 'asker'.

- - - - - - - - - - - - - - - - - - - - - - - - -

EDITO

No había visto bien el código que has puesto en el enlace. El tuyo es más eficiente. Usas directamente la expresión ;)
Gracias WillyWeb! No se me habría ocurrido hacer uso de ella de ese modo.

WillyWeb
04/07/18, 08:13:46
He encontrado una página en la que alguien pregunta lo mismo y recibe (entre otras) la siguiente respuesta...

Caravantes, ¿has llegado a probar ese script para sed? Tengo curiosidad por ver cuánto tarda ese proceso. :pensando:

Caravantes
04/07/18, 18:43:28
Caravantes, ¿has llegado a probar ese script para sed?

No, eso está fuera de mi comarca. Smart escribió "Y por qué no probar con sed...?" lo cual picó un poco mi curiosidad (nadie me había presentado a ese SED); por eso hice una búsqueda en Google y encontré eso que parece servir para resolver el problema, pero yo solo pretendía pasarle esa pista a Smart o a cualquier otro que tenga soltura con SED y comandos parecidos. Eso no es un jardín sino un bosque tupido, y lo tengo muy difícil para abrirme camino con mi navaja de boy scout. Acabaría haciéndome daño, o perdido, y seguro que terminaba emitiendo un SOS por morse.

WillyWeb
04/07/18, 18:55:39
No, eso está fuera de mi comarca.

:risitas: :risitas: :risitas:

Hombre, no deja de ser un comando de consola. Eso sí, un "poco" más complejo de lo habitual.

Acabaría haciéndome daño, o perdido, y seguro que terminaba emitiendo un SOS por morse.

Bueno. Ahora lo puedes hacer con la linterna. :risitas:

https://www.htcmania.com/showthread.php?p=29034286#post29034286