Correspondendo apenas à primeira ocorrência em uma linha com o Regex

42

Eu sou completamente novo em regex e gostaria muito de receber qualquer ajuda.

A tarefa é simples. Eu tenho um arquivo CSV com registros assim:

12345,67890,12345,67890
12345,67890,12345,67890
12345,67890,12345,67890
12345,67890,12345,67890
12345,67890,12345,67890

Gostaria de substituir a primeira vírgula por um espaço e deixar o restante das vírgulas intactas, para cada linha. Existe uma expressão de expressão regular que corresponderá apenas à primeira vírgula?

Eu tentei isso: ^.....,. Isso corresponde à vírgula; no entanto, também corresponde ao comprimento inteiro da cadeia de caracteres que precede a vírgula; portanto, se eu tentar substituí-lo por um espaço, todos os números também serão excluídos.

cows_eat_hay
fonte
qual ferramenta você está usando? (sed, perl, awk, alguma outra coisa?) #
Mat #
Textpad (Windows)
cows_eat_hay

Respostas:

53

O padrão de correspondência pode ser:

^([^,]+),

Que significa

^        starts with
[^,]     anything but a comma
+        repeated one or more times (use * (means zero or more) if the first field can be empty)
([^,]+)  remember that part
,        followed by a comma

Em, por exemplo, perl, a correspondência e a substituição inteiras se pareceriam com:

s/^([^,]+),/\1 /

A peça de substituição apenas pega a coisa toda que corresponde e a substitui pelo primeiro bloco que você lembrou e acrescenta um espaço. O coma é "descartado" porque não está no primeiro grupo de captura.

Esteira
fonte
Impressionante! Obrigado, Mat, funcionou muito bem. Na verdade, ele não funcionou no Textpad (acho que o regex deles é limitado), então acabei baixando o PowerGrep e usei a pesquisa e substituí-lo pela expressão que você forneceu e funcionou muito bem. Obrigado também pela boa explicação, ajuda a entender o que está acontecendo.
cows_eat_hay
7
s/,/ /

Por padrão (isto é, sem a gopção), isso substitui apenas a primeira correspondência.

Mork
fonte
1
Esta é realmente a pesquisa do Textpad e substitui a sintaxe?
Daniel Beck
1
Esta é uma sintaxe de sed, perle algumas outras ferramentas.
Pabouk
3

Isso deve corresponder apenas o primeiro número e a vírgula: ^(\d{5}),. Se você deseja devorar todo o resto da linha, altere a regex para isso:^(\d{5}),(.*)$

alex
fonte
Isso também fez o truque. Acabei usando a solução de Mat, mas testei a sua também e funciona. Obrigado pela ajuda!
cows_eat_hay
Por que \d{5}não [^,]*? Isso seria pelo menos mais genérico.
26418 JustinCB
2

A solução mais elegante é usar a correspondência lenta:

s/^(.+?),/\1 /

que agrupará caracteres movendo-se do início da string ( ^) para o final por um caractere ( .+?) em cada etapa até encontrar o primeiro sinal de vírgula. Todo esse grupo, juntamente com a primeira ocorrência de vírgula, será substituído pelo grupo ( \1) e pelo caractere de espaço.

ghost28147
fonte
Observe que isso não corresponde a uma linha que não contém vírgula (um valor único em uma linha). Combinando qualquer * pode ser melhor do que um +modos/^(.*?),/\1 /
Jeff Puckett
Você também pode fazer s/^([^,]*),/\1 /, o que corresponderia ao início, qualquer coisa que não seja uma vírgula, depois uma vírgula. Além disso, você não sabe que s//isso não muda nada que não corresponde?
23618 JustinCB
1

O TextPad sempre teve a capacidade de usar a notação posix, mas você precisa alterar as configurações em uma caixa de diálogo diferente. Para usar as configurações padrão do TextPad para expressões regulares, é necessário "escapar" dos parênteses de abertura e fechamento:

Substitua o espaço após o CEP de 5 dígitos, no início de cada linha

^\([0-9]+\)[ ]

With tab

\1\t

Como acima, ^ significa início da linha

\ (é um "parêntese de escape" e marca o início da primeira expressão de pesquisa, ou seja, os cinco dígitos

[0-9] + significa um ou mais dígitos (não apenas códigos postais de 5 dígitos)

\) é outro "parêntese de escape" para marcar o final da primeira expressão de pesquisa

[] é apenas um caractere de espaço (você pode deixar de fora os colchetes, mas ninguém poderá vê-lo nesta página da web :-)

Na expressão de substituição

\ 1 é a primeira expressão de pesquisa, a parte entre parênteses acima (um ou mais dígitos)

\ t é um caractere de tabulação

Portanto, o comando search and replace procura por um ou mais dígitos, seguidos por um espaço. Em seguida, substitui tudo isso pelo mesmo grupo de dígitos seguido por uma guia.

Eu não acho que exista uma maneira simplesmente de encontrar "um espaço que vem depois de 5 dígitos" para que você possa substituir o espaço sem tocar nos dígitos. Você precisa encontrar os 5 dígitos (a primeira string) seguidos pelo espaço (a segunda string). Em seguida, embora pareça redundante ou complicado, SUBSTITUA a sequência original de 5 dígitos com ITSELF, seguida pela guia (a segunda sequência).

Todo mundo que sabe disso esquece que os novatos não têm idéia disso. É por isso que estou explicando isso para você, meu amigo.

Ed Poor Math Tutor e Programador de Computador aposentado New York City

user423655
fonte
0

Para corresponder apenas à primeira ocorrência de qualquer expressão de expressão regular, remova todos os sinalizadores. Cada expressão de expressão regular vem com os seguintes sinalizadores possíveis e normalmente usa o sinalizador global que corresponderá a mais de uma ocorrência:

  • / g = Com esse sinalizador, a pesquisa procura todas as correspondências, sem ela - somente a primeira correspondência é retornada
  • / i = não diferencia maiúsculas de minúsculas
  • / m = modo de múltiplas linhas
  • / s = tudo. para corresponder o caractere de nova linha \ n
  • / u = unicode
  • / y = modo fixo (pesquisa em local específico)
Michael Scarpace
fonte