2012-06-11 14 views
6

Necesito una expresión regular para contar el número de columnas en una cadena delimitada por tuberías en java. Los datos de la columna siempre estarán entre comillas dobles o estarán vacíos.Regex para dividir una cadena delimitada por | cuando no está encerrado entre comillas dobles

por ejemplo:

"1234"|"Name"||"Some description with ||| in it"|"Last Column" 

Lo anterior debe ser contado como 5 columnas incluyendo una columna vacía después de la columna "Nombre".

Gracias

+0

¿Desea contar solo o desea extraer los datos también? – nhahtdh

+0

Solo necesito el recuento de columnas. – Nash

+1

puede dividir usando '\" \ | 'y obtener la longitud de la matriz –

Respuesta

8

Ésta es una forma de hacerlo:

String input = 
    "\"1234\"|\"Name\"||\"Some description with ||| in it\"|\"Last Column\""; 
// \_______/ \______/\/\_________________________________/ \_____________/  
//  1  2 3     4       5 

int cols = input.replaceAll("\"[^\"]*\"", "") // remove "..." 
       .replaceAll("[^|]", "")  // remove anything else than | 
       .length() + 1;     // Count the remaining |, add 1 

System.out.println(cols); // 5 

OMI no es muy robusta sin embargo. No recomendaría usar expresiones regulares si planea manejar citas escapadas, por ejemplo.

+0

Usted me ganó. También señale que la cita escapada puede ser un problema. +1 – nhahtdh

+0

Lo hice en la última línea :-) – aioobe

+1

+1 ASCII art bien formado –

2

Levemente mejor las expresiones en aioobe's answer:

int cols = input.replaceAll("\"(?:[^\"\\]+|\\.)*\"|[^|]+", "") 
       .length() + 1; 

Maneja escapa entre comillas, y utiliza una sola expresión para eliminar todo excepto los delimitadores.

1

Aquí hay una expresión regular que utilicé hace un tiempo que también trata con citas escapadas Y delimitadores escapados. Probablemente sea excesivo para sus requisitos (columnas de conteo) pero tal vez lo ayude a usted u otra persona en el futuro con su análisis sintáctico.

(?<=^|(?<!\\)\|)(\".*?(?<=[^\\])\"|.*?(?<!\\(?=\|))(?=")?|)(?=\||$) 

and broken down as: 
(?<=^|(?<!\\)\|)    // look behind to make sure the token starts with the start anchor (first token) or a delimiter (but not an escaped delimiter) 
(       // start of capture group 1 
    \".*?(?<=[^\\])\"   // a token bounded by quotes 
    |       // OR 
    .*?(?<!\\(?=\|))(?=")?  // a token not bounded by quotes, any characters up to the delimiter (unless escaped) 
    |       // OR 
          // empty token 
)       // end of capture group 1 
(?=\||$)      // look ahead to make sure the token is followed by either a delimiter or the end anchor (last token) 

when you actually use it it'll have to be escaped as: 
(?<=^|(?<!\\\\)\\|)(\\\".*?(?<=[^\\\\])\\\"|.*?(?<!\\\\(?=\\|))(?=\")?|)(?=\\||$) 

Es complicado, pero no hay método para esta locura: Otras expresiones regulares que googled caerían sobre si una columna al principio o al final de la línea estaba vacía, cotizaciones delimitados estaban en lugares extraños, la línea o la columna comenzó o finalizó con un delimitador que se escapó, y un montón de otros escenarios de borde marginal.

El hecho de que esté utilizando una tubería como delimitador hace que esta expresión regular sea aún más difícil de leer/comprender. Un consejo es cuando ves un tubo en sí mismo "|", es un OR condicional en expresiones regulares, y cuando se escapó "\ |", es tu delimitador.

Cuestiones relacionadas