Adicionar espaço antes da letra maiúscula

8

Eu tenho uma corda:

AddData
TestSomething
TellMeWhoYouAre

e assim por diante. Quero adicionar espaço antes de letras maiúsculas. Como eu posso fazer isso?

HeroFromEarth
fonte
7
O que você deseja fazer quando houver letras maiúsculas consecutivas? exemploIClimbALadder
glenn jackman
1
Na verdade, eu tenho algumas strings ReadFileFromCDDrivee a solução do @Kusalananda funciona muito bem.
HeroFromEarth 02/02

Respostas:

16

Usando sede assumindo que você não deseja um espaço na frente da palavra:

$ sed 's/\([^[:blank:]]\)\([[:upper:]]\)/\1 \2/g' file.in
Add Data
Test Something
Tell Me Who You Are

A substituição procurará uma letra maiúscula imediatamente após outro caractere que não seja um espaço em branco e inserirá um espaço entre os dois.

Para seqüências com mais de um caractere maiúsculo consecutivo, como WeAreATeam, isso produz We Are ATeam. Para classificar isso, execute a substituição uma segunda vez:

$ sed -e 's/\([^[:blank:]]\)\([[:upper:]]\)/\1 \2/g' \
      -e 's/\([^[:blank:]]\)\([[:upper:]]\)/\1 \2/g' file.in
Kusalananda
fonte
1
Esta resposta não adicionará um espaço antes de uma letra maiúscula se for precedida por uma letra maiúscula. Por que escrever dessa maneira, quando o OP não impôs nenhuma restrição a ele?
LarsH
@LarsH Corrigido.
Kusalananda
Não, você não fez. Você não pode ter correspondências sobrepostas em uma regex, mesmo com um gsinalizador. Tente echo ThisIsATest | sed 's/\(.\)\([[:upper:]]\)/\1 \2/g'(seu comando) para ver por que não funciona.
Curinga
@Wildcard Wonky, mas funciona. Você tem uma sugestão melhor usando BREs?
Kusalananda
Na verdade, ele não diz que não há espaço no início, então s/[A-Z]/ \0/gé totalmente satisfatório ... `s / [AZ] / \ 0 / g; s / ^ // 'se você realmente se importa.
Michael Homer
12

Perl, usando expressões regulares lookbehind e lookahead com largura zero:

$ perl -pe 's/(?<=\w)(?=[A-Z])/ /g'  file.in 

Tell Me Who You Are                    ## TellMeWhoYouAre
I Am A Regular Expression User         ## IAmARegulaExpressionUser

Esta versão também está separando letras maiúsculas consecutivas.

JJoao
fonte
1
Isso se transforma ReadFileFromUSBDriveno Read File From U S B Driveque o OP queria Read File From USB Drive.
Kusalananda
1
@ Kusalananda, obrigado por apontar. (Receio não ver isso escrito na pergunta). Em situações reais (entendimento de programação, expansão de palavras-chave e variantes do CamelCase), é comum usar um critério básico (dividido em maiúsculas ou o oposto) e ter um dicionário de exceções.
JJoao
1
Desculpe, foi algo que o OP escreveu nos comentários da minha resposta. Concordo, é difícil fazer isso sem uma lista de palavras de algum tipo.
Kusalananda
2
sed -r -e "s/([^A-Z])([A-Z])/\1 \2/g"

Adicione espaço entre uma letra que não seja uma letra maiúscula e uma letra que seja uma letra maiúscula

ka3ak
fonte
A brevidade é aceitável, mas explicações mais completas são melhores. . Além disso, qual é o objetivo de [^^]("não é um sinal de intercalação ( ^)")?
Kusalananda
@Kusalananda Você está certo. O espaço não será inserido entre ^ e Add em "^ AddData". Eu editei minha resposta.
Ka3ak
0

Solução Python:

#!/usr/bin/env python
from __future__ import print_function
import sys

with open(sys.argv[1]) as f:
    for line in f:
        for char in line:
            if char.isupper():
               print(" "+char,end="")
            else:
               print(char,end="")

Execução de teste:

$ ./add_space_to_upper.py input.txt                        
 Add Data
 Test Something
 Tell Me Who You Are
Sergiy Kolodyazhnyy
fonte
Você deseja print(line[0], end="")seguir for char in line[1:]:para evitar a impressão desse espaço indesejado no início de cada linha de saída.
Paul Evans