创建一个 PHP、Go 和 Python Quine Relay

发布: (2026年2月11日 GMT+8 22:42)
3 分钟阅读
原文: Dev.to

Source: Dev.to

介绍

我创建了一个涉及 PHP、Go 和 Python 的 Quine 中继,并将一步步解释它是如何工作的。

PHP Quine (QuineRelay.php)

<?=eval($_='print "package main;import\42fmt\42;func main(){fmt.Print(\140print(r\47\47\47<?=eval(\44_=\47$_\47);\47\47\47)\140)}";');

八进制表示

在 PHP 的双引号字符串中,像 \42 这样的序列会被解释为八进制 ASCII 码:

OctalASCIICharacter
4234" (双引号)
4739' (单引号)
14096` (反引号)

使用八进制表示可以避免在 Go 或 Python 字符串中出现这些字符时需要进行转义。

PHP 代码工作原理

  • 变量 $_ 保存一个字符串(用单引号包裹),其中包含了带有八进制转义的 Go 源码。
  • eval($_=…) 首先求值外层的 PHP 字符串,将八进制转义转换为对应字符。
  • 在双引号字符串内部,$_ 会被展开,把相同的 PHP 源码插入生成的 Go 程序——这种自引用是 Quine 的关键。

运行该 PHP 脚本会输出下面的 Go 代码。

生成的 Go 代码

package main;import:"fmt";func main(){fmt.Print(`print(r'''<?=eval($_='print "package main;import\42fmt\42;func main(){fmt.Print(\140print(r\47\47\47<?=eval(\44_=\47$_\47);\47\47\47)\140)}";');''')`)}
  • 这段 Go 程序使用分号写成一行(Go 编译器会自动插入分号)。
  • 使用反引号作为字符串字面量,能够在其中直接包含单引号和双引号而无需转义。

执行这段 Go 程序会打印出下面的 Python 代码。

生成的 Python 代码

print(r'''<?=eval($_='print "package main;import\42fmt\42;func main(){fmt.Print(\140print(r\47\47\47<?=eval(\44_=\47$_\47);\47\47\47)\140)}";');''')
  • 三引号原始字符串(r'''…''')让我们保留八进制转义并避免进一步的转换。
  • 运行该 Python 脚本会重新生成最初的 PHP 源码。

返回 PHP

运行上述 Python 代码会得到原始的 PHP Quine:

<?=eval($_='print "package main;import\42fmt\42;func main(){fmt.Print(\140print(r\47\47\47<?=eval(\44_=\47$_\47);\47\47\47)\140)}";');

总结

一个三语言的 Quine 中继看似复杂,但通过利用八进制表示和仔细的字符串引用,实现过程就变得相当直接。希望本文能帮助你探索并编写更多的 Quine! 🙂

0 浏览
Back to Blog

相关文章

阅读更多 »

Savior:低层设计

磨练 Go:Low‑Level Design 我回到绘图板上进行面试准备并提升我的问题解决能力。软件开发正处于一个...