Title Text:I searched my .bash_history for the line with the highest ratio of special characters to regular alphanumeric characters, and the winner was: cat out.txt | grep -o “[[(].*[])][^)]]*$” … I have no memory of this and no idea what I was trying to do, but I sure hope it worked.<
Origin:https://xkcd.com/1638/
https://www.explainxkcd.com/wiki/index.php/1638:_Backslashes
反斜線們
大多数编程语言都使用字符串文字的概念,它只是某些分隔符之间的文本,通常是引号。例如,“Hello,world”是一个字符串文字。表示的文本是Hello,没有引号的世界。但是,也会写入引号以标记字符串的开头和结尾。当文本本身包含引号时,这是一个问题,如“This is a”引用的“string”。单词“quoted”周围的引号旨在成为文本的一部分,但语言处理器可能会将其混淆为字符串的结尾,因此这将是在这些字符串之外引用的两个字符串(可能导致语法错误) )。
为了避免这个问题,转义字符(通常是反斜杠)被添加到非字符串终止引号。因此,之前的文本将被写为“This is a a”引用的“字符串”。语言处理器将仅使用引号字符替换每次出现的字符串,并且字符串终止于不紧跟反斜杠的引号字符。在这种情况下,生成的文本字符串将是“这是一个”引用的“字符串” 。
但是,现在的问题是预期的文本本身可能包含反斜杠。例如,文本“C:\”现在将被解释为包含引号字符的未终止字符串。为避免这种情况,字面反斜杠也会使用第二个反斜杠进行转义,即代替“C:\”我们编写“C:\\”,其中语言处理器将\\解释为单个反斜杠,并且引号终止字符串以给出C:\作为输出。
这种反斜杠的加倍发生在大多数编程和脚本语言中,但也发生在其他语法结构中,例如正则表达式。因此,当这些语言中的几种结合使用时,反斜杠会以指数方式堆积(每个图层必须加倍斜杠数)。请参阅下面的反斜杠爆炸示例和备选方案。
这种反斜杠爆炸被称为倾斜牙签综合征,并且可能在许多情况下发生。以下是漫画中所有条目的说明。
标题文本中的反斜杠爆炸是关于一个bash命令(它使用反斜杠来转义参数)调用grep实用程序,该实用程序按照通过正则表达式指定的模式(也使用反斜杠转义特殊字符)搜索文本。这导致命令中连续出现3个反斜杠,如果搜索的文本也包含反斜杠,则可能很容易成为连续7个反斜杠。
即使是完全理解这个概念的高级用户也经常很难确定在给定情况下需要多少反向波。仔细计算反斜杠的数量,然后注意到有一个错误,所以整个事情都行不通,这是绝望的沮丧。在某种程度上,只要继续投入反斜杠直到工作,而不是试图推断出正确的数字是什么,就变得更容易了。
目前还不清楚标题文本中的正则表达式是否有效。关于表达式有效性的长篇讨论已经在这个解释的谈话页面上发生了。事实上,网站的许多编辑经常在技术上非常合格[需要引证],无法确定表达是否有效,为漫画的笑话增加了一个元层。这是书呆子狙击的一个例子(哦,具有讽刺意味的\!\!\!\)。
列表中的条目[编辑]
前四个示例的名称(有些)基于它们实际生成的内容:
反斜杠:1个反斜杠,适当命名
真正的反斜杠:2个反斜杠被正确标记,因为它们确实是指转义反斜杠。
真正的反斜杠:3个反斜杠表示转义反斜杠,后跟未转义反斜杠。前两个反斜杠将组合成一个真正的反斜杠,而第三个反斜杠将与后面的字符组合形成一个转义序列。因此这个名称没有多大意义,因为这是两个转义序列,而不是一个“非常真实”的序列。
实际反斜杠,实际上这次:4个反斜杠形成一个单反斜杠两次转义(第一次转义产生两个反斜杠,第二次转义使每个反斜杠加倍)。这很常见,甚至Python正则表达式库的文档都有一个名为正则表达式操作的部分,它明确地提到了“\\\\”。在这种情况下,反斜杠必须转义一次才能成为正则表达式的一部分,然后再一次转义为正则表达式在Python字符串中。这是参考前面的例子没有包含足够的转义的事实命名的。
剩下的五个反斜杠示例有越来越多的隐藏名称(解释),并没有提到反斜杠转义的任何更多实际用法:更长的反斜杠:5个反斜杠将是一个双重逃脱的反斜杠加上一个未转义的反斜杠。漫画中对长者的提及有很多含义。它通过幻想媒体而闻名;最着名的是“长老日”,这是The Silmarillion的中土世界的第一个年代,或多或少是指环王的前传。最近它被用于哈利波特的宇宙中,死亡之神称为长老魔杖,由老木制成,是最后一本书“哈利波特与死亡圣器”中非常重要的一部分。其他例子是克苏鲁神话中的长老神,以及龙与地下神话中的各种“长老”魔法物品和生物。
反斜杠逃离屏幕并进入你的大脑:6个反斜杠是“逃避”一词的游戏,因为反斜杠应该是一个“逃脱角色”,但显然不是“逃离屏幕”并进入你的大脑。这也可以理解为当程序员超越长老反斜杠领域时,他的脑子里正在反复思考……
反斜杠如此真实,它超越了时间和空间:7个反斜杠比逃离屏幕更进一步,因为它们现在超越了时间和空间
反斜杠结束所有其他文本:8个反斜杠将是一个三重转义的反斜杠(与4个反斜杠相同,但有一个额外的转义层)。它被称为“结束所有其他文本”,即如果有人连续使用八个文本,则不应再有文本。但是最后一个例子中可能会有更多内容。
真正的名字Ba’al,Soul-Eater:鈭?反斜杠(显示11,但后跟“……”表示他们永远持续)。如果你能写出无限数量的反斜杠,它实际上就是真正的名字Ba’al,Soul-Eater。这表明,如果你继续滥用这样的反斜杠,你最终会被一个恶魔吞噬,例如Beelzebub,因为他是如此轻率……以前在1419年提到过Ba’al:在电话和1246的标题文本中: 淡蓝色圆点。
反斜杠爆炸和替代[编辑]
反斜杠爆炸的一个合理示例是Web服务器上的PHP脚本,该脚本编写带有正则表达式的JavaScript代码以在客户端上运行。如果JavaScript代码必须测试一个字符串以查看它是否具有双反斜杠,那么正则表达式将执行以下操作:
\\\\
前两个反斜杠表示单个反斜杠,后两个也表示单个反斜杠,因此这将搜索两个连续的反斜杠。
而JavaScript将是:
正则表达式( “\\\\\\\\”)测试(STR)。
其中每两个反斜杠表示字符串中只有一个反斜杠,因此JavaScript中的8个反斜杠在正则表达式中变为4个反斜杠。
但是,由于这个JavaScript代码是通过PHP脚本编写的,因此PHP代码将是:
echo“RegExp(\”\\\\\\\\\\\\\\\\\“)。test(str);”;
哪里:
echo这个词是写一些东西的PHP命令
第一个引号开始字符串
RegExp( – 包括左括号 – 按字面意思书写
“这是一个要写的字面引用
前两个斜杠产生一个斜杠
依此类推,直到写入8个反斜杠
下一个\“产生一个文字引号字符
).test(str);字面意思是写的
下一个引号完成字符串。
最后一个分号终止echo命令
因此,所呈现的场景已从一个简单的\\测试升级到连续不少于十七个反斜杠,而没有退出最常见的操作。
如果我们更进一步尝试编写输出PHP脚本的Java程序,我们将:
System.out.println(“echo \”RegExp(\\\“\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ \ “)测试(STR); \”;“);
在这里,我们连续有35个反斜杠:前34个在PHP脚本中生成我们需要的17个,最后一个用于转义引号字符。 (这更接近真正的名字Ba’al,Soul-Eater)。
某些编程语言提供了替代匹配字符串文字分隔符,以限制需要转义分隔符的情况。通常,可以使用单引号或双引号开始和结束字符串。如果打算使用单引号,如果双引号用于字符串文字或“这是’引用’字符串”,则允许用户编写“This is a”引用的“字符串”。两种分隔符不能在同一个字符串文字中使用,但是如果需要构造包含两种引号的字符串,则通常可以连接两个字符串文字,每个字符串文字使用不同的分隔符。在现代编程语言中似乎流行的另一个特性是为字符串分隔符提供替代语法,专门用于限制倾斜牙签综合症。例如,在Python中,以r“开头的字符串文字是”原始字符串“[1],其中没有进行转义处理,对于在C#中以@”开头的字符串具有类似的语义。这允许用户在Python中编写r“C:\ Users”或在C#中编写@“C:\ Users”而无需转义反斜杠。这不允许将终止分隔符嵌入到字符串的中间并阻止使用反斜杠将换行符编码为\ n,但在编写正则表达式的字符串编码时会派上用场,其中反斜杠是转义一个或多个其他标点字符或速记字符类(例如,\ s表示空格字符)。例如,当在HTML中查找锚标签时,我可以将正则表达式编码为&lt; [Aa] \ s [^&gt;] *&gt;。如果我将此正则表达式表示为原始字符串文字,我的代码看起来像r“&lt; [Aa] \ s [^&gt;] *&gt;”而不是“&lt; [Aa] \\ s [^&gt;] *&gt;”。这里的重点是倾斜牙签综合症是一个真正的问题,它影响了编程语言的实现。