Analisar um literal de cadeia de caracteres Python


9

O desafio é analisar uma string como o Python e imprimir o conteúdo da string.

  • Entrada (argumento da linha de comando ou stdin) : uma literal de cadeia de caracteres (por exemplo "hello") (ou vários literais, consulte concatenação de literal de cadeia abaixo)
  • Saída (stdout) : o conteúdo da string (por exemplo hello)

Regras para analisar a sequência:

  • Um literal de cadeia é colocado entre pares de aspas simples ( 'a'), aspas duplas ( "a"), aspas simples triplas ( '''a''') ou aspas duplas triplas ( """a"""). A primeira recorrência do tipo de aspas que abriu a sequência finaliza a sequência.
  • A barra invertida escapa: \' dentro de uma cadeia torna-se ', \"torna "- \\se e torna - se \. Você não precisa implementar outras escapes de barra invertida. Uma barra invertida que não faz parte de uma sequência de escape permanece uma barra invertida.
  • Concatenação literal de string: o conteúdo dos literais de string adjacentes é concatenado. Por exemplo, "hello" 'world'torna-se helloworld.
  • A entrada pode conter espaços que não fazem parte de nenhum literal.
  • Você não precisa oferecer suporte a nenhum outro tipo de espaço em branco, nem dentro nem fora de literais.

Regras adicionais:

  • eval, exece coisas semelhantes não são permitidas para analisar o literal ou partes dele.
  • Você pode assumir que a entrada é válida.
  • Você pode assumir um comprimento máximo de entrada de 1023 caracteres.

Exemplos:

  • "hello" ' world' -> hello world
  • """\"""'\\\A""" -> """'\\A
  • ( '''"""'''"""'''""" ) (sem parênteses, mas com espaços) -> """'''

O menor código vence.


A saída deve ter um formato que possa ser armazenado ou é suficiente para imprimi-la e terminar com ela?
18713

@ David Impressão, é tudo o que você precisa fazer.
Flornquake

Assim, em (por exemplo) "\ z", o código é especificamente necessário para gerar a barra invertida e o z? Mas "se torna apenas um apóstrofo, mesmo que apareça entre aspas duplas ou triplas? Isso está correto?
breadbox

@breadbox Exatamente.
Flornquake

O código deve suportar seqüências de caracteres brutas? E quanto à concatenação de cadeias não brutas e brutas?
Bakuriu 19/07/2013

Respostas:


4

Perl, 54 caracteres

#!/usr/bin/perl -p
s/ |("""|'''|"|')((\\?.)*?)\1/$2/g;s/\\(["'\\])/$1/g

Quando eu estava postando isso, notei que é quase idêntico à solução Ruby de Jan Dvorak. Estou um pouco impressionado com a sua similaridade, de fato, mas vou dizer "Grandes mentes pensam da mesma forma" e deixar para lá.

Este programa destaca um caso de canto estranho na contagem de caracteres nos scripts Perl: Pela minha leitura, a presença de aspas simples no script significa que preciso contar a -popção como dois caracteres em relação ao meu total. Normalmente, ao calcular o tamanho dos scripts Perl, o caractere inicial do traço nas opções é considerado livre, com a justificativa de que ele pode ser empacotado com o -eque introduz o programa corretamente ... você precisa inserir o script na linha de comando. As aspas simples exigem muito escape, portanto, para evitar essa penalidade, preciso contá-la como um script executado a partir de um arquivo e, portanto, recebo os caracteres #!/usr/bin/perlde graça, mas não os de opção. É um pouco confuso.


2
Se você quer ser diferente, (('|")\2{2}?)tem o mesmo comprimento que("""|'''|"|')
Peter Taylor

3

C, 178 caracteres

char*p,*q,b[1024];d;main(t){for(p=q=gets(b);*p=*q++;)
d?*p==92&!(*q-*p&&*q-34&&*q-39)?*p++=*q++:*p-d||t&&*q-d|q[1]-d?++p:
(d=0,q+=2*t):*p-32?d=*p,t=*q==d&q[1]==d,q+=2*t:0;puts(b);}

Essa é uma daquelas soluções C em que tudo é feito dentro de um grupo de cadeias de operadores ternários.

O programa funciona copiando caracteres de volta para o mesmo buffer, substituindo os metacaracteres. dmantém o delimitador quando dentro de uma sequência e té verdadeiro se o delimitador for uma citação tripla.


Eu acho que você precisa incluir um incremento extra condicional da variável de controle do loop. Para 'foo \\' bar ', fornece foo \ ar', que parece substituir \\ por \, mas continua a análise com o \ recém-inserido, vendo o próximo token como \ '.
manatwork

Na verdade, esse exemplo é uma entrada inválida. 'foo\\'refere-se à string foo \, que é seguida por um caractere que não é um espaço em branco nem um delimitador de string.
embalagem de pão

Opa Eu interpretei mal essa regra. Então é claro que seu código está correto.
manatwork

3

Rubi, 74 73 caracteres

puts gets.gsub(/('''|"""|'|")((\\?.)*?)\1|./,'\2').gsub /\\([\\'"])/,'\1'

O núcleo aqui são duas regexes: O primeiro determina os limites da cadeia e seleciona apenas o conteúdo. A alteração existe para remover tudo que não está dentro das cordas e também descarta as cordas não fechadas.As barras invertidas são tratadas como possesive-opcional seguidas por qualquer coisa. Portanto,Como o mecanismo regex não (\\?.)retornará para entradas válidas (obrigado @breadbox), uma única barra invertida não poderá corresponder lá. As cotações são tratadas por meio de repetição lenta. O segundo regex remove uma barra invertida antes de cada caractere escapável. A regex depende do mecanismo para sempre escolher a alternativa mais à esquerda primeiro.

Também considerei uma abordagem de máquina de estado, mas ficou bastante grande (19 estados x classes de 4 caracteres) em comparação com a solução regex. Ainda posso postar a máquina do estado se alguém estiver interessado.


Uma pequena falha neste método: 'foo \\' bar 'se torna foo \ em vez de' foo \ 'bar'.
manatwork

@ manatwork isso está correto, a menos que algo tenha sido perdido na formatação. A primeira barra invertida escapa à segunda. 'foo\\'é a primeira corda e bar'está fora de um contexto de string quando a entrada é'foo\\'bar'
John Dvorak

Opa Não faço ideia de como eu o calculei anteriormente. Claro que está correto. Desculpa.
Manatwork

Quando tento executar isso, recebo uma mensagem de erro: "aninhado *? + No regexp". Existe alguma versão mínima ou sinalizador de tempo de execução necessário?
embalagem de pão

@breadbox Não verifiquei outras versões, mas estou executando o ruby ​​1.9.3 (JRuby 1.7.2). devo assumir pelo menos 1.9.3 e editá-lo em?
John Dvorak
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.