问题描述
在bash
或sh
中,我猜任何以#
开头的都是评论。
但是在bash
脚本中我们写道:
#!/bin/bash
在Python脚本中,有:
#!/bin/python
这是否意味着#
本身是评论而#!
不是?
最佳解决方案
在脚本运行之前使用#!
行,然后在脚本运行时忽略。
你问的是shebang line和普通评论之间有什么区别。
以#!
开头的行与使用#
开头的任何其他行一样多。如果#!
是文件的第一行或其他任何位置,则为true。 #!/bin/sh
有效,但解释器本身无法读取。
#
不是所有编程语言中的注释,但是,如您所知,它是Bourne-style shell中的注释,包括sh
和bash
(以及大多数non-Bourne-style shell,如csh
)。这是also a comment in Python。它是各种配置文件中的注释,根本不是脚本(如/etc/fstab
)。
假设shell脚本以#!/bin/sh
开头。这是一个注释,解释器(shell)忽略#
字符后面的所有内容。
#!
行的目的不是为解释器提供信息。 #!
系列的目的是告诉操作系统(或任何进程启动解释器)使用什么作为解释器。
-
如果您将脚本作为可执行文件调用,例如,通过运行
./script.sh
,系统将查询第一行,以查看是以#!
开头,后跟零个或多个空格,后跟命令。如果是,则运行该命令,并将脚本名称作为其参数。在此示例中,它运行/bin/sh script.sh
(或技术上,/bin/sh ./script.sh
)。 -
如果通过显式调用解释器来调用脚本,则永远不会查询
#!
行。因此,如果您运行sh script.sh
,则第一行无效。如果script2.sh
的第一行是#!/usr/games/nibbles
,则运行sh script2.sh
将不会尝试在nibbles
(但./script2.sh
)中打开脚本。
您会注意到,在任何情况下,脚本的扩展名(.sh
)(如果有)都会影响它的运行方式。在Unix-like系统中,这通常不会影响脚本的运行方式。在某些其他系统(如Windows)上,系统可能会完全忽略#!
shebang行,并且扩展可能会确定运行脚本的内容。 (这并不意味着您需要提供脚本扩展,但这是其中一个原因,如果您这样做,它们应该是正确的。)
选择#!
是为了达到这个目的,因为#
开始发表评论。 #!
行用于系统,而不是解释器,解释器应该忽略它。
Shebang Line for Bash Scripts
您(最初)说您使用#!/bin/sh
用于bash
脚本。只有在脚本不需要任何bash
扩展时才应该这样做 – sh
需要能够运行脚本。 sh
并不总是bash
的符号链接。通常,包括在所有最近的Debian和Ubuntu系统上,sh
是dash
的符号链接。
Shebang Line for Python Scripts
您还说(在编辑之前的第一个版本中)您使用#!/bin/sh read by the interpretor
启动Python脚本。如果你的意思是字面意思,那么你绝对应该停止这样做。如果hello.py
以该行开头,则运行./hello.py
执行:
/bin/sh read by the interpretor hello.py
/bin/sh
将尝试执行一个名为read
的脚本(以by the interpretor hello.py
为参数),read
将(希望)找不到,Python解释器永远不会看到你的Python脚本。
如果你犯了这个错误但没有我正在描述的问题,你可能通过明确指定解释器(例如,python hello.py
)来调用你的Python程序,导致第一行被忽略。当您将脚本分发给其他人,或者很久以后使用它们时,可能并不清楚这对他们来说是必要的。现在最好修复它们。或者至少完全删除第一行,这样当它们无法使用./
运行时,错误消息才有意义。
对于Python脚本,如果您知道Python解释器(或将要)的位置,您可以使用相同的方式编写#!
行:
#!/usr/bin/python
或者,如果它是Python 3脚本,则应指定python3
,因为python
几乎总是Python 2:
#!/usr/bin/python3
然而,问题是虽然/bin/sh
应该始终存在,并且/bin/bash
几乎总是存在于bash
随操作系统附带的系统上,但Python可能存在于各种各样的地方。
因此,许多Python程序员使用它代替:
#!/usr/bin/env python
(或者Python 3的#!/usr/bin/env python3
)
这使得脚本依赖于env
在”right place”中而不是依赖于python
在正确的位置。这是件好事,因为:
-
env
几乎总是位于/usr/bin
中。 -
在大多数系统上,无论哪个
python
运行您的脚本都是首先出现在PATH
中的脚本。用#!/usr/bin/env python
开始hello.py
使./hello.py
运行/usr/bin/env python hello.py
,其(实际上)等同于运行python hello.py
。
你不能使用#!python
的原因是:
-
您希望指定的解释器由绝对路径给出(即,从
/
开始)。 -
调用进程将在当前目录中执行
python
。当命令不包含斜杠时搜索路径的行为是特定的shell行为。
有时,Python或其他不是shell脚本的脚本将有一个以#!/bin/sh ...
开头的shebang行,其中...
是其他一些代码。这有时是正确的,因为有一些方法可以使用参数调用Bourne-compatible shell(sh
)以使其调用Python解释器。 (其中一个参数可能包含python
。)但是,对于大多数用途,#!/usr/bin/env python
更简单,更优雅,更有可能以您想要的方式工作。
Shebang Lines in Other Languages
许多编程和脚本语言以及一些其他文件格式使用#
作为注释。对于它们中的任何一个,语言中的文件可以由程序运行,该程序通过在#!
之后的第一行指定程序将其作为参数。
在某些编程语言中,#
通常不是注释,但作为特殊情况,如果第一行以#!
开头,则忽略第一行。这有助于使用#!
语法,即使#
不以其他方式发表评论。
Shebang为不运行脚本的文件行
虽然它不太直观,但任何文件格式都可以容纳以#!
开头的第一行的文件后跟可执行文件的完整路径都可以有一个shebang行。如果你这样做,并且文件被标记为可执行文件,那么你可以像程序一样运行它……使它像文档一样打开。
某些应用程序故意使用此行为。例如,在VMware中,.vmx
文件定义虚拟机。您可以将”run”虚拟机视为一个脚本,因为这些文件标记为可执行文件,并且有一个shebang行,导致它们在VMware实用程序中打开。
Shebang为那些不像脚本运行但是像脚本一样的文件
rm
删除文件。它不是脚本语言。但是,可以运行启动#!/bin/rm
并标记为可执行文件的文件,并在运行它时,在其上调用rm
,将其删除。
这通常被概念化为“文件删除自身”。但该文件根本没有运行。这更像是上面描述的.vmx
文件的情况。
但是,由于#!
行有助于运行简单命令(包括命令行参数),因此您可以通过这种方式执行某些脚本。作为比#!/bin/rm
更复杂的”script”的简单示例,请考虑:
#!/usr/bin/env tee -a
这会以交互方式接收用户输入,将其回送给用户line-by-line,并将其附加到”script”文件的末尾。
有用?不是特别的。概念上有趣吗?完全!是。 (有些。)
概念上类似的编程/脚本概念(只是为了好玩)
-
multiple languages at once的脚本/程序,例如to simulate hashbang functionality in OSes that didn’t have it。 (这些程序被称为polyglots,但这不能与软件开发中的其他多语言感混淆,软件开发是一个程序/项目,其中不同的部分用不同的语言编写。)
-
QBasic /QuickBASIC中的Metacommands,用于向编译器(用于编译代码)发出代码生成选项,但是它们是注释的一部分,因此在实际编译/解释期间被忽略。
次佳解决方案
一个shebang是由字符编号和感叹号(例如”#!”)组成的字符序列,当它作为脚本初始行的最初两个字符出现时。
在* nix操作系统下,当运行以shebang开头的脚本时,程序加载器将脚本初始行的其余部分解析为解释器指令;而是运行指定的解释器程序,将其作为参数传递给尝试运行脚本时最初使用的路径。例如,如果脚本以路径”path/to/your-script”命名,并且它以以下行开头:
#!/bin/sh
然后指示程序加载程序运行程序”/bin/sh”,例如, Bourne shell或兼容shell,将”path/to/your-script”作为第一个参数传递。
因此,脚本以路径”path/to/python-script”命名,并从以下行开始:
#!/bin/python
然后指示加载的程序运行程序”/bin/python”,例如, Python解释器,将”path/to/python-script”作为第一个参数传递。
简而言之,”#”将注释掉一行,而作为脚本初始行的前两个字符出现的字符序列”#!”具有如上所述的含义。
有关详细信息,请参阅Why do some scripts start with #! … ?
来源:这个答案的某些部分来自英语维基百科上的Shebang(Unix)(由维基百科贡献者提供)。本文根据CC-BY-SA 3.0进行许可,与AU上的用户内容相同,因此允许使用归属进行推导。
第三种解决方案
当#!
作为脚本初始行的前两个字符出现时,它被称为shebang
。它在脚本中用于指示要执行的解释器。 shebang
用于操作系统(内核),不用于shell;所以它不会被解释为评论。
礼貌:http://en.wikipedia.org/wiki/Shebang_%28Unix%29
In general, if a file is executable, but actually not an executable (binary) program, and such a line is present, the program specified after #! is started with the scriptname and all its arguments. These two characters # and ! have to be the first two bytes in the file!
详细信息:http://wiki.bash-hackers.org/scripting/basics#the_shebang