解析Python字符串文字


9

挑战在于像Python一样解析字符串并打印字符串的内容。

  • 输入(命令行参数或标准输入):字符串文字(例如"hello")(或多个文字,请参见下面的字符串文字串联
  • 输出(stdout):字符串的内容(例如hello

解析字符串的规则:

  • 字符串文字包含在匹配的单引号('a'),双引号("a"),三重单引号('''a''')或三重双引号("""a""")的匹配对中。打开字符串的引号类型的第一次再次出现将结束字符串。
  • 反斜杠转义: \'字符串中的成为'\"成为"\\成为\。您不需要实现任何其他反斜杠转义。不在转义序列中的反斜杠保留为反斜杠。
  • 字符串文字串联:串联相邻字符串文字的内容。例如,"hello" 'world'变为helloworld
  • 输入中可能包含不属于任何文字的空格。
  • 无论文字内外,您都不需要支持任何其他类型的空格。

附加规则:

  • evalexec并且不允许使用类似的内容来解析其文字或部分内容。
  • 您可以假设输入有效。
  • 您可以假设最大输入长度为1023个字符。

例子:

  • "hello" ' world' -> hello world
  • """\"""'\\\A""" -> """'\\A
  • ( '''"""'''"""'''""" ) (不带括号,但带空格)-> """'''

最短的代码胜出。


输出是否具有可以存储的形式,或者足以打印并使用它完成?
DavidC

@David Printing这就是您需要做的。
flornquake

因此,在(例如)“ \ z”中,代码​​特别需要输出反斜杠和z?但是,即使\出现在双引号或三引号中,它也只是撇号?那是对的吗?
面包箱

@breadbox确实如此。
flornquake

代码应支持原始字符串吗?那么非原始字符串和原始字符串的串联又如何呢?
巴库里

Answers:


4

Perl,54个字符

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

就在我发布这篇文章时,我注意到它几乎与Jan Dvorak的Ruby解决方案相同。实际上,我对它的相似性有点不满意,但是我要说“好主意都一样”,然后放开它。

该程序突出显示了在Perl脚本中计算字符时出现的一个奇怪的极端情况:根据我的阅读,脚本中单引号的存在意味着我需要将该-p选项作为两个字符计入总数。通常,在计算Perl脚本大小时,选项上的初始破折号被认为是免费的,理由是它可以与-e引入适当程序的捆绑在一起,但是您还必须考虑任何额外的转义符您需要在命令行上输入脚本。单引号需要大量转义,因此为避免这种损失,我必须将其计为从文件运行的脚本,因此我#!/usr/bin/perl免费获得,但没有任何选择字符。这有点令人困惑。


2
如果您想与众不同,(('|")\2{2}?)那么长度与("""|'''|"|')
Peter Taylor

3

C,178个字符

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);}

这是所有三元运算符链帮中完成的C解决方案之一。

该程序通过将字符复制回同一缓冲区,覆盖元字符来工作。d当在字符串内部时,保存定界符;t如果定界符为三引号,则为true。


我认为您需要包括条件附加的循环控制变量。对于'foo \\'bar',它给出了foo \ ar',看起来好像它用\替换了\\,但是随后继续使用新输入的\进行解析,将下一个标记视为\'。
manatwork

实际上,该示例是无效输入。'foo\\'指的是字符串foo \,其后是既不是空格也不是字符串定界符的字符。
面包箱

哎呀。我误读了那条规则。那么,当然您的代码是正确的。
manatwork

3

红宝石, 74 73个字符

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

这里的核心是两个正则表达式:第一个正则表达式确定字符串边界并仅选择内容。在那里可以进行更改,以删除字符串内的所有内容,还可以删除未关闭的字符串。反斜杠被视为posssitive-optional(可选),后跟任何东西。从而,由于正则表达式引擎不会(\\?.)回退到有效的输入(感谢@breadbox),因此唯一的反斜杠不能在那里匹配。报价是通过懒惰重复处理的。然后,第二个正则表达式在每个可转义字符之前去除反斜杠。正则表达式取决于引擎始终始终选择最左边的替代项。

我也考虑过一种状态机方法,但与正则表达式解决方案相比,结果非常大(19个状态x 4个字符类)。如果有人感兴趣,我仍然可以发布状态机。


使用此方法的一个小故障:'foo \\'bar'变为foo \,而不是'foo \'bar'。
manatwork

@manatwork,这是正确的,除非格式化丢失了一些内容。第一个反斜杠转义第二个反斜杠。'foo\\'是第一个字符串,并且bar'在输入'foo\\'bar'
为时

哎呀。不知道我是怎么计算的。当然是对的。抱歉。
manatwork

当我尝试运行此命令时,我收到一条错误消息:“在正则表达式中嵌套*?+”。我需要一些最低版本或运行时标志吗?
面包箱

@breadbox我还没有检查其他版本,但是我正在运行ruby 1.9.3(JRuby 1.7.2)。我应该至少假设1.9.3并进行编辑吗?
John Dvorak
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.