Pergunta

Eu não estou muito certo se isso é possível, então eu volto para você.

Eu gostaria de encontrar um regex que irá escolher todos vírgulas que caem conjuntos cotação fora.

Por exemplo:

'foo' => 'bar',
'foofoo' => 'bar,bar'

Este seria escolher a única vírgula na linha 1, depois de 'bar',

Eu realmente não se preocupam com único vs aspas duplas.

Alguém quaisquer pensamentos obtidos? Eu sinto que isso deve ser possível com readaheads, mas meu fu regex é muito fraco.

Foi útil?

Solução

Isso irá corresponder a qualquer cadeia até e incluindo o primeiro não-citado "". É isso que você está querendo?

/^([^"]|"[^"]*")*?(,)/

Se você quiser todos eles (e como um contra-exemplo para o cara que disse que não era possível) você poderia escrever:

/(,)(?=(?:[^"]|"[^"]*")*$)/

que irá corresponder a todos eles. Assim

'test, a "comma,", bob, ",sam,",here'.gsub(/(,)(?=(?:[^"]|"[^"]*")*$)/,';')

substitui todas as vírgulas não citações dentro com ponto e vírgula, e produz:

'test; a "comma,"; bob; ",sam,";here'

Se você precisar dele para trabalhar em quebras de linha basta adicionar a bandeira m (multiline).

Outras dicas

A seguir regexes iria coincidir com todos os da vírgula que estão presentes fora das aspas,

,(?=(?:[^"]*"[^"]*")*[^"]*$)

DEMONSTRA

ou (PCRE apenas)

"[^"]*"(*SKIP)(*F)|,

"[^"]*" corresponde a todos o bloco citado dupla. Ou seja, neste entrada buz,"bar,foo", este regex iria corresponder única "bar,foo". Agora o seguinte (*SKIP)(*F) torna o jogo falhar. Em seguida, ele se move para o padrão que foi próximo ao símbolo | e tenta corresponder caracteres da string restante. Isto é, em nossa , saída próximo ao padrão | irá corresponder somente a vírgula que era apenas após a buz. Note que isso não irá corresponder a vírgula que estava presente dentro de aspas, porque já fazem parte dupla cotado para pular.

DEMONSTRA


O abaixo regex iria coincidir com todos os da vírgula que estão presentes dentro das aspas,

,(?!(?:[^"]*"[^"]*")*[^"]*$)

DEMONSTRA

Embora seja possível cortá-lo com uma regex (e eu gosto de expressões regulares abusando tanto quanto o próximo cara), você vai ficar em apuros mais cedo ou mais tarde tentando substrings manipular sem um analisador mais avançado. formas possíveis de obter em apuros incluir citações mistos, e escapou aspas.

Esta função irá dividir uma string em vírgulas, mas não as vírgulas que estão dentro de uma cadeia simples ou dupla citado. Ele pode ser facilmente estendido com caracteres adicionais para usar como citações (embora pares de caracteres, como «» precisaria de mais algumas linhas de código) e vai mesmo dizer-lhe se você se esqueceu de fechar uma citação em seus dados:

function splitNotStrings(str){
  var parse=[], inString=false, escape=0, end=0

  for(var i=0, c; c=str[i]; i++){ // looping over the characters in str
    if(c==='\\'){ escape^=1; continue} // 1 when odd number of consecutive \
    if(c===','){
      if(!inString){
        parse.push(str.slice(end, i))
        end=i+1
      }
    }
    else if(splitNotStrings.quotes.indexOf(c)>-1 && !escape){
      if(c===inString) inString=false
      else if(!inString) inString=c
    }
    escape=0
  }
  // now we finished parsing, strings should be closed
  if(inString) throw SyntaxError('expected matching '+inString)
  if(end<i) parse.push(str.slice(end, i))
  return parse
}

splitNotStrings.quotes="'\"" // add other (symmetrical) quotes here

Tente esta expressão regular:

(?:"(?:[^\\"]+|\\(?:\\\\)*[\\"])*"|'(?:[^\\']+|\\(?:\\\\)*[\\'])*')\s*=>\s*(?:"(?:[^\\"]+|\\(?:\\\\)*[\\"])*"|'(?:[^\\']+|\\(?:\\\\)*[\\'])*')\s*,

Isso também não permite que strings como “'foo\'bar' => 'bar\\',”.

A resposta de MarkusQ trabalhou muito para mim por cerca de um ano, até que ele não o fez. Eu só tenho um erro de estouro de pilha em uma linha com cerca de 120 vírgulas e 3682 caracteres no total. Em Java, como este:

        String[] cells = line.split("[\t,](?=(?:[^\"]|\"[^\"]*\")*$)", -1);

Aqui está a minha substituição extremamente deselegante que não estouro de pilha:

private String[] extractCellsFromLine(String line) {
    List<String> cellList = new ArrayList<String>();
    while (true) {
        String[] firstCellAndRest;
        if (line.startsWith("\"")) {
            firstCellAndRest = line.split("([\t,])(?=(?:[^\"]|\"[^\"]*\")*$)", 2);
        }
        else {
            firstCellAndRest = line.split("[\t,]", 2);                
        }
        cellList.add(firstCellAndRest[0]);
        if (firstCellAndRest.length == 1) {
            break;
        }
        line = firstCellAndRest[1];
    }
    return cellList.toArray(new String[cellList.size()]);
}

@SocialCensus, o exemplo que você deu no comentário para MarkusQ, onde você joga em 'ao lado do" não funciona com o exemplo MarkusQ deu logo acima que se mudarmos sam para < em> de sam: (teste, uma "vírgula", bob "Sam, " aqui) não tem jogo contra o (,) (= (?:? [^" '] | [" |' ] [^ "'] ") $). na verdade, o problema em si, 'Eu realmente não me importo sobre o único vs aspas duplas', é ambígua. você tem que ser claro o que você quer dizer citando ou com "ou com'. Por exemplo, se a desova permitido ou não? Em caso afirmativo, quantos níveis? Se apenas 1 nível aninhado, o que acontece com uma vírgula fora da citação aninhada interior, mas dentro da citação do assentamento exterior? Você também deve considerar que aspas simples acontecem por si mesmas como apóstrofos (ou seja, como o contra-exemplo que dei anteriormente com Sam). Finalmente, o regex que você fez não aspas simples não é realmente tratar a par com aspas duplas, uma vez que assume o último tipo de aspas é necessariamente uma aspas duplas - e substituindo essa última citação duplo com [ '| "] também tem um problema Se o texto não vem com correta citando (ou se apóstrofos são usados), porém, acho que provavelmente poderia assumir todas as citações são corretamente delineadas.

regexp de MarkusQ responde à pergunta: encontrar todas as vírgulas que têm um número par de aspas duplas após ele (ou seja, são citações fora de casal) e ignorar todas as vírgulas que têm um número ímpar de aspas duplas após ele (ou seja, estão dentro duplo citações). Isso geralmente é a mesma solução que o que você provavelmente vai querer, mas Vamos olhar algumas anomalias. Primeiro, se deixa alguém fora aspas no final, então este regexp encontra todas as vírgulas erradas em vez de encontrar os desejados ou não para combinar com qualquer. Claro que, se uma citação dupla está faltando, todas as apostas estão fora, uma vez que pode não ser claro se a um desaparecido pertence no final ou em vez pertence no início; no entanto, há um caso que é legítimo e onde a regex poderia concebivelmente falhar (esta é a segunda "anomalia"). Se você ajustar o regexp para ir em todas as linhas de texto, então você deve estar ciente de que citando vários parágrafos consecutivos exige que você coloque um único aspas duplas no início de cada parágrafo e deixar de fora a cotação no final de cada parágrafo, exceto no fim do último parágrafo. Isso significa que todo o espaço desses números, a regex irá falhar em alguns lugares e ter sucesso em outros.

Os exemplos e discussões breves do parágrafo citando e de nested citando pode ser encontrada aqui http: //en.wikipedia .org / wiki / Quotation_mark .

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top