Tengo la siguiente cadena:
x = "marchTextIWantToDisplayWithSpacesmarch"
Me gustaría eliminar la parte de 'marcha' al comienzo de la cadena y luego agregar un espacio antes de cada letra mayúscula en el resto para obtener el siguiente resultado:
"Text I Want To Display With Spacesmarch"
Para insertar espacios en blanco, utilicé gsub("([a-z]?)([A-Z])", "\\1 \\2", x, perl= T)
pero no tengo idea de cómo modificar el patrón para que la primera 'marcha' se excluya de la cadena devuelta. Estoy tratando de mejorar en esto para que cualquier ayuda sea muy apreciada.
4 respuestas
No, no puede lograr su reemplazo con un solo gsub
porque en uno de sus requisitos, desea eliminar todas las letras minúsculas que comienzan desde el principio, y su segundo requisito es introducir un espacio antes de cada letra mayúscula, excepto el primera letra mayúscula de la cadena resultante después de eliminar todas las letras minúsculas del comienzo del texto.
Habría sido posible hacerlo en una sola llamada gsub
en casos en los que de alguna manera podemos reutilizar algunos de los caracteres existentes para hacer el reemplazo condicional que no puede ser el caso aquí. Entonces, en el primer paso, puede usar la expresión regular ^[a-z]+
para deshacerse de todas las letras minúsculas solo desde el comienzo de la cadena,
sub('^[a-z]+', '', "marchTextIWantToDisplayWithSpacesmarch")
Dejándote con esto
[1] "TextIWantToDisplayWithSpacesmarch"
Y el siguiente paso puede utilizar esta expresión regular (?<!^)(?=[A-Z])
para insertar un espacio antes de cada letra mayúscula, excepto la primera, ya que es posible que no desee un espacio adicional antes de su oración. Pero puedes combinar ambos y escribirlos así,
gsub('(?<!^)(?=[A-Z])', ' ', sub('^[a-z]+', '', "marchTextIWantToDisplayWithSpacesmarch"), perl=TRUE)
Que te dará la cuerda deseada,
[1] "Text I Want To Display With Spacesmarch"
Editar: Explicación del patrón (?<!^)(?=[A-Z])
Primero, tomemos el patrón (?=[A-Z])
,
Vea los marcadores rosas en esta demostración
Como puede ver, en la demostración, cada letra mayúscula está precedida por una marca rosa que es el lugar donde se insertará un espacio. Pero no queremos que se inserte espacio antes de la primera letra, ya que no es necesario. Por lo tanto, necesitamos una condición en regex, que no seleccionará la primera letra mayúscula que aparece al comienzo de la cadena. Y para eso, debemos usar una mirada negativa detrás de (?<!^)
, lo que significa que No seleccione la posición precedida por el inicio de la cadena y, por lo tanto, esto (?<!^)
ayuda a descartar la letra mayúscula precedida por solo el inicio de la cadena.
Vea esta demostración donde el marcador rosa ha desaparecido de la primera letra mayúscula
Espero que esto aclare cómo se selecciona cada letra mayúscula pero no la primera. Avíseme si tiene alguna consulta adicional.
Puede usar una sola llamada de expresión regular a gsub
junto con trimws
para recortar la cadena resultante:
trimws(gsub("^\\p{Ll}+|(?<=.)(?=\\p{Lu})", " ", x, perl=TRUE))
## => [1] "Text I Want To Display With Spacesmarch"
También es compatible con todas las letras minúsculas Unicode (\p{Ll}
) y mayúsculas (\p{Lu}
).
Consulte la R demo en línea y la demostración de expresiones regulares.
Detalles
^\\p{Ll}+
- 1 o más letras minúsculas al comienzo de la cadena|
- o(?<=.)(?=\\p{Lu})
: cualquier ubicación entre cualquier carácter excepto caracteres de salto de línea y una letra mayúscula.
Aquí hay una alternativa con una sola llamada a gsubfn
regex con alguna lógica ifelse
:
> gsubfn("^\\p{Ll}*(\\p{L})|(?<=.)(?=\\p{Lu})", function(n) ifelse(nchar(n)>0,n," "), x, perl=TRUE,backref=-1)
[1] "Text I Want To Display With Spacesmarch"
Aquí, la parte ^\\p{Ll}*(\\p{L})
coincide con más de 0 letras minúsculas y captura la siguiente mayúscula en el Grupo 1 al que se accederá pasando el argumento n
a la función anónima. Si la longitud n
no es cero, esta alternativa coincide y debemos reemplazarla con este valor. De lo contrario, reemplazamos con un espacio.
Una opción sería capturar la letra mayúscula como un grupo ((...)
) y en el reemplazo crear un espacio seguido de la referencia (\\1
) del grupo capturado
gsub("([A-Z])", " \\1", x)
#[1] "march Text I Want To Display With Spacesmarch"
Si necesitamos eliminar la 'marcha'
sub("\\b[a-z]\\w+\\s+", "", gsub("([A-Z])", " \\1", x))
[#1] "Text I Want To Display With Spacesmarch"
Datos
x <- "marchTextIWantToDisplayWithSpacesmarch"
Como esto está etiquetado como Perl, mis 2 centavos:
¿Puedes encadenar las sustituciones dentro de sub()
y gsub()
? En las versiones perl más nuevas, se puede agregar una opción /r
a la sustitución s///
para que la cadena coincidente pueda ser devuelta "no destructivamente" y luego emparejada nuevamente. Esto permite coincidencias / sustituciones / revanchas sin dominar sintaxis avanzada, por ejemplo :
perl -E '
say "marchTextIWantToDisplayWithSpacesmarch" =~
s/\Amarch//r =~ s/([[:upper:]])/ $1/gr =~ s/\A\s//r;'
Salida
Text I Want To Display With Spacesmarch
Esto parece ser lo que están haciendo @ pushpesh-kumar-rajwanshi y @akrun envolviendo gsub
dentro de sub()
(y viceversa). En general, no creo que perl = T
capture la locura magníficamente avanzada de perl regexps ;-) pero gsub/sub
debe funcionar rápidamente en vectores, ¿no?
Preguntas relacionadas
Nuevas preguntas
r
R es un entorno de software y lenguaje de programación de código abierto y gratuito para computación estadística, bioinformática, visualización y computación en general. Proporcione ejemplos mínimos y reproducibles junto con el resultado deseado. Use dput () para los datos y especifique todos los paquetes no base con llamadas a library (). No incruste imágenes para datos o código, use bloques de código con sangría en su lugar. Para preguntas relacionadas con estadísticas, use https://stats.stackexchange.com.