Jas*_*ick 2 bash shell parsing cmd io-redirection
这个引人入胜的帖子:
在一个看似格式错误的cat
"shell"(一个Linux shell,大概是BASH)的调用中突出了令人惊讶的行为.基本上,shell似乎能够从一系列字符串中的模糊位置获取可执行文件,然后使用I/O重定向到流/文件描述符.
根据我的理解,基本过程是:
1>
(stdout))(这发生在命令中启动可执行进程之前!(例如cat
调用))这导致了一些令人惊讶的逻辑.例如,在执行后的新目录中echo "dog" > cat
:
<cat cat >dog
:从文件中写入"狗" cat
来dog
使用shell工具cat
<cat cat> cat cat
:覆盖第一个命令,留下一个空白cat
文件(不确定在第二个命令的中间发生了什么).
<cat cat> cat cat >dog 2>more
:创建空文件,dog
并用空文件more
覆盖cat
文件.
<cat >dog cat cat <dog >cat
(创建空文件dog
,覆盖cat
w /空文件)
<cat cat >dog 2>much 1>more
:用cat
空文件覆盖; 创建文件dog
/ more
每个包含字符串"dog",创建为空much
(上述列表行为已在BASH
(v4.3.46)上进行了测试.)
现在,在某种程度上,可怜的外壳决定它已经足够了.例如,面对:
<cat dog> cat cat >dog >cat
它抱怨说:
bash:dog:找不到命令
但是有一个额外的惊喜 - 命令实际上已部分完成.与上面的大多数示例一样,它cat
使用空白文件覆盖文件,并创建了一个空白文件dog
.
为了更好地理解" 最流行的Linux shell "和CMD(标准Windows shell)中的复杂I/O重定向处理:
BASH
(Linux)的TCSH
(Linux)的KSH
(Linux)的ZSH
(Linux)的CMD
(视窗)...是这种顺序模糊的I/O重定向解析...
BASH
(Linux)和cmd
(Windows).)stuff.dat>1test.dat<2test.dat
where 1test.dat
和2test.dat
are文件)解析重定向看起来不明确的命令时对于POSIX shell--即尝试实现Posix标准的shell - 解析算法实际上相当简单,并且还在该标准中进行了记录.这包括bash
,ksh
并zsh
从你的列表(以及其他,如dash
),但不能在Windows cmd
.tcsh
类似但不是Posix.
重定向不是"命令模糊".它们被解析并从左到右执行.唯一可能奇怪的部分是它们可能与命令及其参数任意交错,但由于每个重定向都在重定向操作符之前,因此不会产生歧义.
对于简单命令,过程大致如下:
该命令分为单词.重定向运算符之前的单词是重定向; 这些将从命令中删除并保存以供以后处理.
需要注意的是重定向操作符是自定界,所以没有任何区别之间a> b
,a >b
和a>b
.所有这些都是单词a
,重定向运算符>
和单词b
,>b
并将被视为重定向.所以语法<a> b
可能会让人类读者感到困惑(因此应该避免使用),但它不会混淆shell,因为shell将它视为以更正常的方式编写的<a >b
.
开头的主要词ID=
是赋值(其中ID
任何看起来像变量名的东西).这些也被删除以便以后处理.与重定向不同,这些是在第一个单词(如果有的话)之前唯一被识别的,这不是赋值.
剩余的单词(如果有的话)根据扩展规则进行扩展,这可能涉及拆分扩展单词.扩展后的第一个单词(如果有)是命令,其余的单词是命令参数.
重定向从左到右执行.输出重定向(>foo
)创建或截断命名文件; append redirections(>>foo
)只创建文件.
分配已扩展并应用.如果有命令,则分配将应用于命令将运行的子shell环境; 否则,它们将应用于当前的shell环境.
如果有命令,则执行命令参数字作为参数传递给它argc/argv
.
例如,<cat cat> cat cat
似乎让你感到困惑的那条线从左到右解析为:
<cat
,输入重定向cat
,一个命令>cat
,输出重定向cat
一个论点这导致重定向<cat
并>cat
在cat
使用参数调用命令之前执行cat
.<cat
如果cat
在执行该行之前该文件在当前目录中不存在,则第一个redirect()将失败,因此>cat
只有在文件存在时才会执行第二个redirect(); 它会立即截断(清空)文件.除非当前目录在PATH中,否则cat
将从文件执行该命令,该文件/bin/cat
是另一个文件.由于向cat
命令提供了一个参数,因此它不会使用其标准输入,因此<cat
除非导致整个命令失败,否则重定向将无效,除非该文件cat
已存在.由于cat
在执行命令之前文件将被截断cat cat
,因此不会将任何内容写入标准输出,并且文件cat
将保持为空.
关于你的上一个问题:
除了有关错误处理的一些细节之外,这些规则同样适用于所有简单命令,无论是否内置.
该2
在>2foo
不特殊,所以2foo
是一个文件名.FD重复用>&
重定向运算符表示; >&2foo
被视为复制的尝试2foo
,这是无效的,因为2foo
它不是整数.Posix将此视为未指定的行为,因此实际的shell可能会做得很好.有关详细信息,请参见Posix shell规范的第2.7.5节(或至少是官方线).
由于文件不存在或文件的权限不允许操作,重定向可能会失败.如上所述,重定向从左到右执行,这可能在"复杂"情况下起作用.
归档时间: |
|
查看次数: |
132 次 |
最近记录: |