创建一个 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 码:
| Octal | ASCII | Character |
|---|---|---|
| 42 | 34 | " (双引号) |
| 47 | 39 | ' (单引号) |
| 140 | 96 | ` (反引号) |
使用八进制表示可以避免在 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! 🙂