regex help - ignora um char se estiver entre aspas

4

Temos um aplicativo baseado na web no trabalho onde você pode inserir um regex em uma caixa de pesquisa e retornar as correspondências de um banco de dados

Aqui está uma amostra de como as entradas do banco de dados podem se parecer. Eles são delimitados por vírgula (pense em cada registro como uma família - cada família pode ter entre 1 e n entradas):

record1: "john doe"<[email protected]>;male,"jane doe"<[email protected];female
record2: "john smith"<[email protected]>
record3: "smith, jane"<[email protected]>

O que eu preciso fazer é inserir um regex, então eu só obtenho a primeira entrada. Em um cenário de trabalho, a saída seria tudo até o delimitador:

record1: "john doe"<[email protected]>;male
record2: "john smith"<[email protected]>
record3: "smith, jane"<[email protected]>

Na realidade, todas as minhas tentativas estão vendo a vírgula em "smith, jane" como o delimitador.

Como ignoro uma vírgula se estiver entre aspas? (Para o futuro, a capacidade de ignorar vírgulas entre aspas simples também seria boa)

Eu posso somente usar regex, não awk / sed etc e o sabor da regex é POSIX Extended.

    
por oliver CFC 27.05.2013 / 15:10

4 respostas

1

Destaque: você faz precisa detalhar seu ambiente um pouco mais como os comentários apontam.

Aqui está uma tentativa no meu shell Unix com sed
Sim, eu sei que você não quer sed , mas pode ajudar você a construir o regex em seu ambiente.

data.txt: 
"john doe"<[email protected]>;male,"jane doe"<[email protected];female
john_doe"<[email protected]>;male,"jane doe"<[email protected];female

# sed -n 's|^\("[^"]\+"[^,]\+\).*|| p' data.txt 
"john doe"<[email protected]>;male

A ideia de regex aqui é saltar sobre o primeiro par de aspas duplas e depois procurar a vírgula.
Ele falhará se não houver aspas duplas.
Pode ser dimensionado para usar aspas simples.

Atualizar :
Procure por @ seguido por , ...

data.txt: 
"john doe"<[email protected]>;male,"jane doe"<[email protected];female
john_doe"<[email protected]>;male,"jane doe"<[email protected];female

# sed -n 's|\([^@]\+[^,]\+\),.*|| p' data.txt 
"john doe"<[email protected]>;male
john_doe<[email protected]>;male

Agora você obtém os dois casos e também aqueles sem o nome da string ou até <> wrap.
Mas, o seu problema é a dependência do , - quebras para o registro2 e registro3 onde você tem um único e-mail e sem vírgula. Ainda funcionaria se você forçasse um , no final de cada registro.

    
por 27.05.2013 / 17:11
1

Você não pode fazer isso de maneira confiável com expressões regulares . O melhor que você será capaz de fazer será um hack feio baseado em um monte de suposições que são garantidas para quebrar eventualmente se você ousar colocar esse código em produção. (Se você não pode fazê-lo com o poder de fogo de um motor de regex Perl totalmente armado e operacional, então certamente você não pode fazê-lo com expressões regulares estendidas POSIX.)

Em suma, para resolver esse problema de maneira confiável, você precisará encontrar uma maneira de estender o código com o qual está trabalhando, de modo que ele possa fazer uso de uma biblioteca de análise de CSV, ou, na sua falta, precisa escrever um analisador.

É claro que, se você não conseguir modificar o código que está manipulando os arquivos em questão, então você está preso aos hacks feios, o que neste caso é lamentável, já que não vejo nenhuma maneira realmente confiável de produzir o resultado desejado com o POSIX regexes como sua única ferramenta.

    
por 28.05.2013 / 19:53
0

Tentar ignorar uma vírgula entre aspas é problemático porque a vírgula que você deseja encontrar também está "entre aspas" (a cotação final de "john doe" e a cotação em aberto de "jane doe" ). A menos que você assuma que a primeira citação existe, você terá dificuldade em fazer essa distinção.

Tente isso:

^[^<]+<[^>]*>[^,\s]*

Estou assumindo que cada registro terá <email> e qualquer vírgula depois que o email indicar um novo registro. Isso é apenas trocar uma hipótese por outra, mas funcionou no meu teste.

    
por 27.05.2013 / 17:29
0

Use o regex para alterar o delimitador, se aspas externas com algo mais como uma guia:

Padrão ((?: [^, "] |" [^ "] *") +),
Substitua \ 1 \ t

Em seguida, divida por novo delimitador

    
por 13.12.2017 / 17:56

Tags