引子
为什么要写这篇文章呢?实际上还是源于上一篇文章Nginx 配置指南里面一处配置代码给我带来的小纠结:
你需要将静态网页和文件放到一个目录(例如/data/www),将图片等文件放到另一个目录(例如/data/images),然后在nginx.conf中进行配置。这需要在http模块下的server模块内新建两个location模块:
1
2
3
4
5
6
7
8
9
10 http {
server {
location / {
root /data/www;
}
location /images/ {
root /data;
}
}
}
看起来很好理解吧~也可以直接把文件放到一块,直接location配置绝对路径:
1
2
3 location / {
root F:\webapp\portal;
}
发现问题了么?上面的代码块root路径都是以斜杠(/)分隔的,下面的代码块的root路径却是以反斜杠(\)分隔的。两种不同的方式却能同样生效,这个是为什么呢?
作为路径分隔符在windows和Unix系统下的区别
在上文中的例子,不论是正斜杠还是反斜杠(\),都是作为路径分隔符存在的,因此我们首先把他们作为路径分隔符,分别在windows和Unix两种不同内核的系统下进行一波测试。
windows(win7 64位系统)下:
Unix(Ubuntu 14.04.5)下:
可以看出,Unix内核系统,路径格式仅支持正斜杠(/)分隔,而windows的系统,正斜杠(/)反斜杠(\)都支持,这是个很奇妙的差别。
在查询了资料后,我才知道造成这种差别的深层次原因。
windows的命令行(CMD应用程序)跟早期的MS-DOS操作系统的命令格式是前向兼容的。而DOS系统其实有很多历史遗留问题。
DOS系统很大一部分参考(抄袭?)自加里·基尔代尔的更早的一款操作系统CP/M。
CP/M是数字研究公司(1991年被Novell所兼并)在1974年开发,为8位CPU(如Intel 8080、Zilog Z80等)的个人电脑(PC)所设计的操作系统。在PC市场的黎明阶段,它成为被广泛应用的操作系统。可是因为在向16位CPU的转化上错失机会,在以IBM PC/AT以及IBM PC兼容机为中心的16位PC市场上惨败给Microsoft的MS-DOS,从而从市场上消失。虽然CP/M推出了为Intel 8086而设计的“CP/M 86”以及为Motorola 68000而设计的“CP/M 68k”等版本,但用户几乎不存在。
由于CP/M系统是不支持目录的,/被拿来用作命令行参数的标识符,比如说dir /a, dir /w, dir /q等等(Unix用的是”-“),因此,当MS-DOS系统准备支持目录时,/已被占用,只能使用\来表示路径分隔符了。再后来,windows系统诞生之时,命令行因为要跟MS-DOS兼容,只能把DOS的特性沿用了下来,同时又给支持/作为路径分隔符,于是就造成了现在这种正斜杠(/)反斜杠(\)都支持作为路径分隔符的情况的出现。而Unix不存在这种历史遗留问题,从诞生之初就开始使用斜杠(/)作为路径分隔符,因此,两个系统在这种奇怪的地方出现了分叉。
而我当时的那段代码
1 | location / { |
中的root路径,是直接从windows系统中粘贴的路径,因此就会出现这种反斜杠(\)做分隔符的奇怪场景。
对了,在测试过程中还发现了windows系统中使用/和\做分隔符的一个好玩的区别:
- 使用\做分隔符时,在输入二级子目录(比如\zgit\zblog)时,可以提示补全路径,输入z以后按一下tab就帮我把zblog给补全了
- 使用/做分隔符时,在输入二级子目录(比如\zgit\zblog)时,并不能提示补全路径,他给我提示的还是1级子目录的列表,在我输入z以后按一下tab,他帮我补了一个zgit,我输入zb,按tab无反应。这实际上根本无可用补全功能。
因此,仅在windows下做目录操作时,还是使用反斜杠(\)做分隔符系统支持度更强些,使用体验也更好一些。
广义方面的区别
正斜杠(/)
正斜杠(/)是我们平时很多时候都会用到的斜杠,我们经常会见到这样的写法:小明/小红/小强,你/我/他等等。这种格式在各种文章里面十分常见,表示“或”或者是“和”的意思。
浏览器中URL的层级URL标记符(//)以及路径分隔符(/)也是由正斜杠(/)组成,例如”https://zh.wikipedia.org/wiki/", 可以看到里面清一色的都是正斜杠(/)。使用正斜杠(/)的原因据说是web网站最早是在Unix系统下运行的,于是沿袭了Unix的那一套路径表述方式,因此使用正斜杠(/)作为分隔符。
正斜杠(/)也可以用作“除法”或者“分号”的作用,比如说”100÷4”我们在计算机上输入时,由于除号比较难输,经常就会写成”100/4”,效果是完全一致的。这种用法应该是从“分号”演化来的,毕竟”4/3”你看做“三分之四”还是看做“4除以3”,都是可以的。
连续两个正斜杠(/)可做“注释”之用,在C++/C#/Java/JavaScript/PHP等主流编程语言中基本上通用:
日期也可以使用正斜杠(/)分隔年月日,例如”2017/11/17”,也可以用美国标准”11/17/2017”,都表示2017年11月17日。
最后,斜线除了上述用法,也成为连字号的代替品。例如美国空军的飞机序号。”85-1000”是第1000架飞机在1985年制造,使用斜线”85-1001/1050”表示首批连串50部制造的飞机。
1 | // 在控制台打印hello world! |
反斜杠(\)
比起正斜杠(/)的诸多用处,反斜杠(\)的用处可就少多了。如果你还是动不动就用到反斜杠(\),证明你肯定是一个程序员。
反斜杠(\)除了可以在windows下可以做路径分隔符外,最常用的功能就是做转义字符了。许多正则表达式语言都会将它视为字面意义和元字符之前的切换。例如\n是换行,\0是空字符,它们表示的实际上都是一个字符(char);而在一些数学软件(如MATLAB)和维基百科上,可以使用反斜线输入希腊字母。\pi会转成π,\lambda会转成λ。由于反斜杠(\)存在转义字符的作用,因此我们常常在一些代码里面看到形如”C:\\Windows\\System32\\cmd.exe”的路径格式(实际上你看到的双反斜杠(\),我在markdown格式下输入了连续4个反斜杠…),并不代表实际路径是这样的,而是其中连续两个反斜杠(\)发生了“化学反应”,第一个反斜杠(\)代表对后面部分进行转义,而对反斜杠(\)的转义还是反斜杠(\),因此虽然连续输入两个反斜杠(\),但是实际输出时只有一个反斜杠(\)。
另外,在某些程序语言的命令行中,例如在linux中,反斜线常被放在一行的末尾用来指示编译器忽略其后的换行符,使得下一行会被当做同一行语句。这种情况下,反斜线作为一个强制换行符,将代码拆解成“连续行”。
小结
通读完这篇文章,相信你对正斜杠(/)和反斜杠(\)的作用不会再有疑惑了。最后,我再用一张图来总结一下两者各自的功能,以供各位看官整理记忆。
TIPS
看了这么一大堆正斜杠(/)和反斜杠(\),是不是头都大了呢?没关系,要想记忆区分正斜杠(/)反斜杠(\),可以把他们想象为笔画上的撇(丿)和捺(㇏),一撇一捺是为八,第一笔正斜,第二笔反斜(/\),这样是不是好记多了呢?