当Bash运行您的脚本时,它会将其解析为代码还是命令?Bash是否像Python一样编译并运行您的脚本,还是只是通过其命令解析器运行它?
Bash是一种单通道解释器,这意味着它一次只读取一个命令,进行解释和运行。其他类型的shell(sh、ksh、zsh、csh等)也是如此。
以下是一个示例。我有一个名为test.sh
的三行脚本,其内容如下:
echo one
echo two
'
当以 bash test.sh
的方式运行时,它会输出以下内容:
one
two
test.sh: line 3: unexpected EOF while looking for matching `''
test.sh: line 4: syntax error: unexpected end of file
它成功运行了第一个和第二个命令,然后遇到了悬空的单引号并抛出了错误。
假设我们在Perl中编写相同的代码,test.pl
:
print "one\n"
print "two\n"
'
并使用 perl test.pl
运行它。我们得到:
syntax error at test.pl line 2, near "print"
Can't find string terminator "'" anywhere before EOF at test.pl line 3.
echo“Hello”;echo“echo World”>> $0
。 - el.pescado - нет войнеeval
的情况下,解析器可以重新调用并修改optree,但那是另一件事。 - Evan Carrollbash
shell以纯文本方式运行您的脚本。它不会将文件预编译为某种形式的字节码。reader_loop()
来处理输入。这在循环内调用read_command()
,然后调用execute_command()
。read_command()
还包含对parse_command()
的调用,该函数调用YACC解析器函数yyparse()
,这意味着解析是基于一行一行进行的,而不是在某个大型编译阶段中提前完成。i
重命名为更长的名称,time for ((i=0;i<100000;++i)); do :; done
将会慢得多。请注意,此处不提供解释。 - Jeffrey Cash另一种看出 bash
每次处理一行输入的方法是创建一个明显有语法错误的脚本,并在一个有效的 echo
语句之后运行该脚本,然后运行该脚本。在产生语法错误之前,bash
将会产生一些输出:
echo output
()
产生
$ bash tmp.sh
output
tmp.sh: line 2: syntax error near unexpected token ')'
tmp.sh: line 2: `()'
ksh
解释器会将整个文件预读到缓冲区中,而另一版则只是在文件中移动一个指针;这意味着对于第二个版本,你可以运行该文件并在文件早期进行更改,但正在运行的副本可能会因为指针不再指向一行开头而变得混乱,因为你已更改了偏移量 - 另一版继续运行缓存的副本。两种方法都有优点和缺点,但我更喜欢缓存。 - Paul Hodges