fbpx
维基百科

Bash

BashUnix shell的一種,在1987年由布萊恩·福克斯為了GNU計劃而编写。1989年釋出第一個正式版本,原先是計劃用在GNU作業系統上,但能运行于大多数类Unix系统的操作系统之上,包括LinuxMac OS X v10.4起至macOS Mojave都將它作為預設shell,而自macOS Catalina,預設Shell以zsh取代。

Bash
Bash會話的截圖
原作者布萊恩·福克斯
首次发布1989年6月8日,​34年前​(1989-06-08
当前版本
  • 5.2.21 (2023年11月9日;穩定版本)[1]
源代码库
  • git.savannah.gnu.org/cgit/bash.git
编程语言C語言
操作系统
系統平台GNU
语言多語言(gettext
类型Unix shell命令語言英语command language
许可协议GPLv3+[6]
网站www.gnu.org/software/bash/

Bash是Bourne shell的後繼相容版本與開放原始碼版本,它的名稱來自Bourne shell(sh)的一个双关语(Bourne again / born again):Bourne-Again SHell。

Bash是一个命令处理器,通常运行于文本窗口中,并能执行用户直接输入的命令。Bash还能从文件中读取命令,这样的文件称为脚本。和其他Unix shell 一样,它支持文件名替换(通配符匹配)、管道here文档、命令替换、变量,以及条件判断和循环遍历的结构控制语句。包括关键字、语法在内的基本特性全部是从sh借鉴过来的。其他特性,例如历史命令,是从cshksh借鉴而来。总的来说,Bash虽然是一个满足POSIX规范的shell,但有很多扩展。

一个名为Shellshock的安全漏洞在2014年9月初被发现,并迅速导致互联网上的一系列攻击。这个漏洞可追溯到1989年发布的1.03版本。

历史 编辑

由于理查德·斯托曼对于之前一位开发者的进度不满,布莱恩·福克斯从1988年1月10日开始开发Bash。斯托曼和自由软件基金会希望到一个能够运行已有的shell脚本的自由软件。他们把这看作是建成一个基于BSD和GNU的完全自由的操作系统的战略的重要部分。这是他们自己注资的几个项目之一。福克斯作为自由软件基金会的雇员承担这项工作。1989年6月8日,福克斯发布Bash的beta版本,版本号为.99。在福克斯离开于1992年中期到1994年中期的某个时候离开自由软件基金会之前,他一直担任Bash的主要维护者。之后,他的工作被传递给另一个早期贡献者,切特·雷米(Chet Ramey)。

从那时起,在Linux用户当中sh在很大度上成为最流行的shell,并成为许多Linux发行版默认的交互式shell(不过Almquist shell可能是默认的脚本shell)。在苹果公司的 OS X 操作系统上也是如此。Bash 也被移植到 Microsoft Windows(通过CygwinMinGW)。通过DJGPP项目,Bash被移植到了DOS。通过许多终端模拟软件,Bash被移植到Novell NetWareAndroid。微软在2016年的Build大会上宣布,Windows 10 添加一个Linux子系统,完全支持Bash和其他Ubuntu下的二进制程序。

2014年9月24日,Stephane Chazelas,一位工作于英国,致力于Unix/Linux和网络通信方面的专家,发现Bash的一个安全漏洞。这个漏洞被命名为Shellshock,并被分配编号 CVE-2014-6271、CVE-2014-6277、CVE-2014-7169。这个漏洞非常严重,因为使用Bash的CGI脚本会变得脆弱,使得攻击者可以执行任意的代码。这个漏洞与Bash通过环境变量把函数定义传递给shell子进程的方式有关。

语法与特性 编辑

bash的命令语法是Bourne shell命令语法的超集。数量庞大的Bourne shell脚本大多不经修改即可以在bash中执行,只有那些引用了Bourne特殊变量或使用了Bourne的内置命令的脚本才需要修改。bash的命令语法很多来自Korn shell(ksh)和C shell(csh),例如命令行编辑,命令历史,目录栈,$RANDOM$PPID变量,以及POSIX的命令置换语法:$(...)。作为一个交互式的shell,按下TAB键即可自动补全已部分输入的程序名,文件名,变量名等等。

使用'function'关键字时,Bash的函数声明与Bourne/Korn/POSIX脚本不兼容(Korn shell 有同样的问题)。不过Bash也接受Bourne/Korn/POSIX的函数声明语法。因为许多不同,Bash脚本很少能在Bourne或Korn解释器中运行,除非编写脚本时刻意保持兼容性。然而,随着Linux的普及,这种方式正变得越来越少。不过在POSIX模式下,Bash更加符合POSIX。

bash的语法针对Bourne shell的不足做了很多扩展。其中的一些列举在这里。

花括号扩展 编辑

花括号扩展是一个从C shell借鉴而来的特性,它产生一系列指定的字符串(按照原先从左到右的顺序)。这些字符串不需要是已经存在的文件。

$ echo a{p,c,d,b}e ape ace ade abe $ echo {a,b,c}{d,e,f} ad ae af bd be bf cd ce cf 

花括号扩展不应该被用在可移植的shell脚本中,因为Bourne shell产生的结果不同。

#! /bin/sh # 传统的shell并不产生相同结果 echo a{p,c,d,b}e # a{p,c,d,b}e 

当花括号扩展和通配符一起使用时,花括号扩展首先被解析,然后正常解析通配符。因此,可以用这种方法获得当前目录的一系列JPEG和PNG文件。

ls *.{jpg,jpeg,png} # 首先扩展为*.jpg *.jpeg *.png,然后解析通配符 echo *.{png,jp{e,}g} # echo显示扩展结果;花括号扩展可以嵌套。 

除了列举备选项,还可以用“..”在花括号扩展中指定字符或数字范围。较新的Bash版本接受一个整数作为第三个参数,指定增量。

$ echo {1..10} 1 2 3 4 5 6 7 8 9 10 $ echo file{1..4}.txt file1.txt file2.txt file3.txt file4.txt $ echo {a..e} a b c d e $ echo {1..10..3} 1 4 7 10 $ echo {a..j..3} a d g j 

当花括号扩展和变量扩展一起使用时,变量扩展解析于花括号扩展之后。有时有必要使用内置的eval函数

$ start=1; end=10 $ echo {$start..$end} # 由于解析顺序,无法得到想要的结果 {1..10} $ eval echo {$start..$end} # 首先进行变量扩展的解析 1 2 3 4 5 6 7 8 9 10 

使用整数 编辑

与Bourne shell不同的是bash不用另外生成进程即能进行整数运算。bash使用((...))命令和$[...]变量语法来达到这个目的:

 VAR=55 # 将整数55赋值给变量VAR  ((VAR = VAR + 1)) # 变量VAR加1。注意这里没有'$'  ((++VAR)) # 另一种方法给VAR加1。使用C语言风格的前缀自增  ((VAR++)) # 另一种方法给VAR加1。使用C语言风格的后缀自增  echo $((VAR * 22)) # VAR乘以22并将结果送入命令  echo $[VAR * 22] # 同上,但为过时用法 

((...))命令可以用于条件语句,因为它的退出状态是0或者非0(大多数情况下是1),可以用于是与非的条件判断:

 if((VAR == Y * 3 + X * 2))  then  echo Yes  fi  ((Z > 23)) && echo Yes 

((...))命令支持下列比较操作符:'==', '!=', '>', '<', '>=',和'<='。

bash不能在自身进程内进行浮点数运算。当前有这个能力的unix shell只有Korn shellZ shell

输入输出重定向 编辑

bash拥有传统Bourne shell缺乏的I/O重定向语法。bash可以同时重定向标准输出和标准错误,这需要使用下面的语法:

 command &> file 

这比等价的Bourne shell语法"command > file 2>&1"来的简单。2.05b版本以后,bash可以用下列语法重定向标准输入至字符串(称为here string):

 command <<< "string to be read as standard input" 

如果字符串包括空格就需要用引号包裹字符串。

例子: 重定向标准输出至文件,写数据,关闭文件,重置标准输出。

 # 生成标准输出(文件描述符1)的拷贝文件描述符6  exec 6>&1  # 打开文件"test.data"以供写入  exec 1>test.data  # 产生一些内容  echo "data:data:data"  # 关闭文件"test.data"  exec 1>&-  # 使标准输出指向FD 6(重置标准输出)  exec 1>&6  # 关闭FD6  exec 6>&- 

打开及关闭文件

 # 打开文件test.data以供读取  exec 6<test.data  # 读文件直到文件尾  while read -u 6 dta  do  echo "$dta"  done  # 关闭文件test.data  exec 6<&- 

抓取外部命令的输出

 # 运行'find'并且将结果存于VAR  # 搜索以"h"结尾的文件名  VAR=$(find . -name "*h") 

进程内的正则表达式 编辑

bash 3.0支持进程内的正则表达式,使用下面的语法:

 [[ string =~ regex ]] 

正则表达式语法同regex(7) man page所描述的一致。正则表达式匹配字符串时上述命令的退出状态为0,不匹配为1。正则表达式中用圆括号括起的子表达式可以访问shell变量BASH_REMATCH,如下:

 if [[ abcfoobarbletch =~ 'foo(bar)bl(.*)' ]]  then  echo The regex matches!  echo $BASH_REMATCH -- outputs: foobarbletch  echo ${BASH_REMATCH[1]} -- outputs: bar  echo ${BASH_REMATCH[2]} -- outputs: etch  fi 

使用这个语法的性能要比生成一个新的进程来运行grep命令优越,因为正则表达式匹配在bash进程内完成。如果正则表达式或者字符串包括空格或者shell 关键字,(诸如'*'或者'?'),就需要用引号包裹。Bash 4 开始的版本已经不需要这么做了。

转义字符 编辑

$'string' 形式的字符串会被特殊处理。字符串会被展开成string,并像C语言那样将反斜杠及紧跟的字符进行替换。反斜杠转义序列的转换方式如下:

转义字符
转义字符 扩展成...
\a 响铃符
\b 退格符
\e ANSI转义符,等价于\033
\f 馈页符
\n 换行符
\r 回车符
\t 水平制表符
\v 垂直制表符
\\ 反斜杠
\' 单引号
\nnn 十进制值为nnn的8-bit字符(1-3位)
\xHH 十六进制值为HH的8-bit字符(1或2位)
\cx control-X字符

扩展后的结果将被单引号包裹,就好像美元符号一直就不存在一样。

双引号包裹的字符串前若有一个美元符号($"...")将会使得字符串被翻译成符合当前locale的语言。如果当前locale是C或者POSIX,美元符号会被忽略。如果字符串被翻译并替换,替换后的字符串仍被双引号包裹。

关联数组 编辑

Bash 4.0 开始支持关联数组,通过类似AWK的方式,对于多维数组提供了伪支持。

$ declare -A a # 声明一个名为a的伪二位数组 $ i=1; j=2 $ a[$i,$j]=5 # 将键 "$i,$j" 与值 5 对应 $ echo ${a[$i,$j]} 

移植性 编辑

调用Bash时指定 --posix 或者在脚本中声明 set -o posix ,可以使得Bash几乎遵循 POSIX 1003.2 标准。若要保证一个Bash脚本的移植性,至少需要考虑到 Bourne shell,即Bash取代的shell。Bash有一些传统的 Bourne shell 所没有的特性,包括以下这些:

  • 某些扩展的调用选项
  • 命令替换(即$())(尽管这是 POSIX 1003.2 标准的一部分)
  • 花括号扩展
  • 某些数组操作、关联数组
  • 扩展的双层方括号判断语句
  • 某些字符串生成操作
  • 进程替换
  • 正则表达式匹配符
  • Bash特有的内置工具
  • 协进程

键盘快捷键 编辑

Bash默认使用Emacs的快捷键,可以通过 set -o vi 让它使用Vi的快捷键

进程管理 编辑

Bash有两种执行命令的模式:批处理模式、并发模式。

批处理模式 编辑

要以 批处理模式 执行命令(即按照顺序),必须用;分隔,例子如下:

command1 ; command2 

在这个例子中,当command1执行完毕,即执行command2

并发模式 编辑

使command1后台运行,则单独在结尾处使用&,例子如下:

command1 & 

要并发执行两个命令,它们必须用&分隔,例子如下:

command1 & command2 

在这种情况下,command1 在后台执行(通过&),从而立即将控制返回到shell,以执行command2

通过 Control+Z 可以将当前进程挂起(放置后台并暂停运行),可通过 fg 命令恢复至前台,也通过bg将挂起的进程后台运行。

查看进程状态 编辑

所有进程的情况,我们可以通过jobs命令查看,包含正在后台运行和停止了的。

$ jobs [1]- Running command1 & [2]+ Stopped command2 

上例的输出结果中,中括号包围的数字(如: "[1]" 和 "[2]" )为job的ID号。加号(+)用于指定fgbg命令的默认对象job。减号( - )用于指定,若当前的默认对象job退出后,下一个默认对象job是谁。"Running" 和 "Stopped" 表示进程状态。 最后一个字段为命令。[7]


总结:

  • 一般命令在前台执行(fg),执行完毕后,控制返回给用户。
  • 在命令后面加上&,它会在后台执行(bg),并将特殊的环境变量$!设置为该任务的进程ID。这时shell可以并发执行其他命令。
  • 后台程序试图写入数据到终端设备时(与写入标准输出不同)可能被阻塞。
  • shell可以等待一个后台任务执行完成,只需使用wait命令,加上进程ID或者任务序号;也可以等待所有的后台任务,只需使用不加参数的wait

启动脚本 编辑

bash启动的时候会运行各种不同的脚本。

当bash作为一个登录的交互shell被调用,或者作为非交互shell但带有--login参数被调用时,它首先读入并执行文件/etc/profile。然后它会依次寻找~/.bash_profile~/.bash_login,和~/.profile,读入并执行第一个存在且可读的文件。--noprofile参数可以阻止bash启动时的这种行为。

当一个登录shell退出时,bash读取并执行~/.bash_logout文件,如果此文件存在。

当一个交互的非登录shell启动后,bash读取并执行~/.bashrc文件。这个行为可以用--norc参数阻止。--rcfile file参数强制bash读取并执行指定的file而不是默认的~/.bashrc

如果用sh来调用bash,bash在启动后进入posix模式,它会尽可能模仿sh历史版本的启动行为,以便遵守POSIX标准。用sh名字调用的非交互shell不会去读取其他启动脚本,--rcfile参数无效。

当bash以POSIX模式启动时(例如带有--posix参数)它使用POSIX标准来读取启动文件。在此模式下,交互shells扩展变量ENV,从以此为文件名的文件中读取命令并执行。

bash会探测自己是不是被远程shell守护程序运行(通常是rshd)。如果是,它会读取并执行~/.bashrc中的命令。但是rshd一般不会用rc相关参数调用shell,也不会允许指定这些参数。

Bash与Bourne shell和csh启动脚本的比较 编辑

Bash的特性是从Bourne shell和csh发展而来,因此一定程度上允许同Bourne shell的启动文件共享,并提供一些csh用户熟悉的启动特性。

设置可继承的环境变量 编辑

Bourne shell登陆时使用 ~/.profile 来设置环境变量,这些环境变量可以被子进程继承。Bash可以以兼容的方式使用~/.profile ,只需在Bash自有的脚本中显式执行下面这行代码。通过在~/.profile 中避免使用Bash特有的语法,就可以和Bourne shell保持兼容性。

. ~/.profile 

别名和函数 编辑

更通用的函数以及借鉴自csh的“别名(alias)”很大程度上取代了Bourne shell的别名(alias)和函数。然而这两个特性一般不能从登录式shell中继承,在该登录式shell的子shell中,它们必须被重新定义。尽管有个环境变量ENV可以被用于这个问题,不过 csh 和 Bash 都可以用子shell的启动脚本直接处理。在Bash当中,~/.bashrc 是交互式子shell启动时执行的脚本。如果想要在登录式shell中使用 ~/.bashrc 定义的函数,可以在 ~/.bash_login 的环境变量后面加上这样一行:

. ~/.bashrc 

登录与登出时执行的命令 编辑

最初登录时,csh 执行 ~/.login ,可以执行一些只在登录时执行的操作,例如显示系统负载、硬盘状态、是否收到新邮件、在日志中记录登录时间,等等。Bourne shell 可以在 ~/.profile 文件中模拟这种行为,但并没有预先定义文件名。可以在 ~/.bash_profile 文件的环境变量设置和函数定义的后面添加这样一行:

. ~/.bash_login 

与之类似,csh还有一个文件 ~/.logout ,这个文件只在登录式shell退出时执行。Bash与之对应的文件是 ~/.bash_logout ,并且不需要专门的设置。在 Bourne shell 中,trap 这个内置工具可以实现类似的效果。

兼容旧环境的Bash启动脚本示例 编辑

下面这个 ~/.bash_profile 的框架与 Bourne shell 兼容,并且为 ~/.bashrc~/.bash_login 提供类似于 csh 的语义。[ -r 文件名] 测试指定文件是否存在,如果不存在,跳过 && 后面的部分

[ -r ~/.profile ] && . ~/.profile # 只使用Bourne shell的语法设置环境变量 if [ -n "$PS1" ] ; then # 判断是否是交互式shell  [ -r ~/.bashrc ] && . ~/.bashrc # 加载~/.bashrc(tty、prompt、函数设置等)  [ -r ~/.bash_login ] && . ~/.bash_login # 执行登录式shell登录时的任务 fi # if块的结束标志 

Bash 启动脚本与操作系统相关的问题 编辑

一些 Unix 和 Linux 版本常在 /etc 放置 Bash 的系统级启动脚本。Bash在其标准的初始化过程中执行它们,不过其他启动脚本可以按照不同于Bash启动序列文档所述的顺序来读取这些文件。root 用户的文件默认内容,以及新用户被创建时系统提供的默认文件可能有问题。启动 X Window系统 的启动脚本可能使用用户的 Bash 启动脚本尝试在 窗口管理器 启动之前设置用户的环境变量。这些问题常常可以通过使用 ~/.xsession 或者 ~/.xprofile 来读取 ~/.profile 而解决。

参见 编辑

脚注 编辑

  1. ^ bash-5.2.21.tar.gz. 2023年11月9日 [2023年11月9日]. 
  2. ^ . [2016-04-09]. (原始内容存档于2018-09-01). 
  3. ^ Why does Apple ship bash 3.2?. apple.stackexchange.com. [2019-04-25]. (原始内容于2016-04-16). 
  4. ^ Missing source code - GPL compliance? · Issue #107 · Microsoft/WSL. GitHub. [2019-04-25]. (原始内容于2019-09-24). 
  5. ^ GNU Bash. Softpedia. SoftNews. [2016-04-09]. (原始内容于2017-10-21). 
  6. ^ GNU Project. README file. [2019-04-25]. (原始内容于2019-04-26). Bash is free software, distributed under the terms of the [GNU] General Public License as published by the Free Software Foundation, version 3 of the License (or any later version). 
  7. ^ jobs.1p - Linux manual page. man7.org. [2020-01-14]. (原始内容于2020-01-14). 

外部链接 编辑

bash, 此條目可参照英語維基百科相應條目来扩充, 若您熟悉来源语言和主题, 请协助参考外语维基百科扩充条目, 请勿直接提交机械翻译, 也不要翻译不可靠, 低品质内容, 依版权协议, 译文需在编辑摘要注明来源, 或于讨论页顶部标记, href, template, translated, page, html, title, template, translated, page, translated, page, 标签, unix, shell的一種, 在1987年由布萊恩, 福克斯為了gnu計劃而编写, 19. 此條目可参照英語維基百科相應條目来扩充 若您熟悉来源语言和主题 请协助参考外语维基百科扩充条目 请勿直接提交机械翻译 也不要翻译不可靠 低品质内容 依版权协议 译文需在编辑摘要注明来源 或于讨论页顶部标记 a href Template Translated page html title Template Translated page Translated page a 标签 Bash Unix shell的一種 在1987年由布萊恩 福克斯為了GNU計劃而编写 1989年釋出第一個正式版本 原先是計劃用在GNU作業系統上 但能运行于大多数类Unix系统的操作系统之上 包括Linux與Mac OS X v10 4起至macOS Mojave都將它作為預設shell 而自macOS Catalina 預設Shell以zsh取代 BashBash會話的截圖原作者布萊恩 福克斯首次发布1989年6月8日 34年前 1989 06 08 当前版本5 2 21 2023年11月9日 穩定版本 1 源代码库git wbr savannah wbr gnu wbr org wbr cgit wbr bash wbr git编程语言C語言操作系统Unix like 2 macOS 系統包括較舊的GPLv2版本 當前版本可通過第三方獲得 3 Windows 透過WSL提供 為較新的GPLv3 版本 4 5 系統平台GNU语言多語言 gettext 类型Unix shell 命令語言 英语 command language 许可协议GPLv3 6 网站www wbr gnu wbr org wbr software wbr bash wbr Bash是Bourne shell的後繼相容版本與開放原始碼版本 它的名稱來自Bourne shell sh 的一个双关语 Bourne again born again Bourne Again SHell Bash是一个命令处理器 通常运行于文本窗口中 并能执行用户直接输入的命令 Bash还能从文件中读取命令 这样的文件称为脚本 和其他Unix shell 一样 它支持文件名替换 通配符匹配 管道 here文档 命令替换 变量 以及条件判断和循环遍历的结构控制语句 包括关键字 语法在内的基本特性全部是从sh借鉴过来的 其他特性 例如历史命令 是从csh和ksh借鉴而来 总的来说 Bash虽然是一个满足POSIX规范的shell 但有很多扩展 一个名为Shellshock的安全漏洞在2014年9月初被发现 并迅速导致互联网上的一系列攻击 这个漏洞可追溯到1989年发布的1 03版本 目录 1 历史 2 语法与特性 2 1 花括号扩展 2 2 使用整数 2 3 输入输出重定向 2 4 进程内的正则表达式 2 5 转义字符 2 6 关联数组 2 7 移植性 2 8 键盘快捷键 2 9 进程管理 2 9 1 批处理模式 2 9 2 并发模式 2 9 3 查看进程状态 3 启动脚本 3 1 Bash与Bourne shell和csh启动脚本的比较 3 1 1 设置可继承的环境变量 3 1 2 别名和函数 3 1 3 登录与登出时执行的命令 3 1 4 兼容旧环境的Bash启动脚本示例 3 2 Bash 启动脚本与操作系统相关的问题 4 参见 5 脚注 6 外部链接历史 编辑由于理查德 斯托曼对于之前一位开发者的进度不满 布莱恩 福克斯从1988年1月10日开始开发Bash 斯托曼和自由软件基金会希望到一个能够运行已有的shell脚本的自由软件 他们把这看作是建成一个基于BSD和GNU的完全自由的操作系统的战略的重要部分 这是他们自己注资的几个项目之一 福克斯作为自由软件基金会的雇员承担这项工作 1989年6月8日 福克斯发布Bash的beta版本 版本号为 99 在福克斯离开于1992年中期到1994年中期的某个时候离开自由软件基金会之前 他一直担任Bash的主要维护者 之后 他的工作被传递给另一个早期贡献者 切特 雷米 Chet Ramey 从那时起 在Linux用户当中sh在很大度上成为最流行的shell 并成为许多Linux发行版默认的交互式shell 不过Almquist shell可能是默认的脚本shell 在苹果公司的 OS X 操作系统上也是如此 Bash 也被移植到 Microsoft Windows 通过Cygwin和MinGW 通过DJGPP项目 Bash被移植到了DOS 通过许多终端模拟软件 Bash被移植到Novell NetWare和Android 微软在2016年的Build大会上宣布 Windows 10 添加一个Linux子系统 完全支持Bash和其他Ubuntu下的二进制程序 2014年9月24日 Stephane Chazelas 一位工作于英国 致力于Unix Linux和网络通信方面的专家 发现Bash的一个安全漏洞 这个漏洞被命名为Shellshock 并被分配编号 CVE 2014 6271 CVE 2014 6277 CVE 2014 7169 这个漏洞非常严重 因为使用Bash的CGI脚本会变得脆弱 使得攻击者可以执行任意的代码 这个漏洞与Bash通过环境变量把函数定义传递给shell子进程的方式有关 语法与特性 编辑bash的命令语法是Bourne shell命令语法的超集 数量庞大的Bourne shell脚本大多不经修改即可以在bash中执行 只有那些引用了Bourne特殊变量或使用了Bourne的内置命令的脚本才需要修改 bash的命令语法很多来自Korn shell ksh 和C shell csh 例如命令行编辑 命令历史 目录栈 RANDOM和 PPID变量 以及POSIX的命令置换语法 作为一个交互式的shell 按下TAB键即可自动补全已部分输入的程序名 文件名 变量名等等 使用 function 关键字时 Bash的函数声明与Bourne Korn POSIX脚本不兼容 Korn shell 有同样的问题 不过Bash也接受Bourne Korn POSIX的函数声明语法 因为许多不同 Bash脚本很少能在Bourne或Korn解释器中运行 除非编写脚本时刻意保持兼容性 然而 随着Linux的普及 这种方式正变得越来越少 不过在POSIX模式下 Bash更加符合POSIX bash的语法针对Bourne shell的不足做了很多扩展 其中的一些列举在这里 花括号扩展 编辑花括号扩展是一个从C shell借鉴而来的特性 它产生一系列指定的字符串 按照原先从左到右的顺序 这些字符串不需要是已经存在的文件 echo a p c d b e ape ace ade abe echo a b c d e f ad ae af bd be bf cd ce cf花括号扩展不应该被用在可移植的shell脚本中 因为Bourne shell产生的结果不同 bin sh 传统的shell并不产生相同结果 echo a p c d b e a p c d b e当花括号扩展和通配符一起使用时 花括号扩展首先被解析 然后正常解析通配符 因此 可以用这种方法获得当前目录的一系列JPEG和PNG文件 ls jpg jpeg png 首先扩展为 jpg jpeg png 然后解析通配符 echo png jp e g echo显示扩展结果 花括号扩展可以嵌套 除了列举备选项 还可以用 在花括号扩展中指定字符或数字范围 较新的Bash版本接受一个整数作为第三个参数 指定增量 echo 1 10 1 2 3 4 5 6 7 8 9 10 echo file 1 4 txt file1 txt file2 txt file3 txt file4 txt echo a e a b c d e echo 1 10 3 1 4 7 10 echo a j 3 a d g j当花括号扩展和变量扩展一起使用时 变量扩展解析于花括号扩展之后 有时有必要使用内置的eval函数 start 1 end 10 echo start end 由于解析顺序 无法得到想要的结果 1 10 eval echo start end 首先进行变量扩展的解析 1 2 3 4 5 6 7 8 9 10 使用整数 编辑 与Bourne shell不同的是bash不用另外生成进程即能进行整数运算 bash使用 命令和 变量语法来达到这个目的 VAR 55 将整数55赋值给变量VAR VAR VAR 1 变量VAR加1 注意这里没有 VAR 另一种方法给VAR加1 使用C语言风格的前缀自增 VAR 另一种方法给VAR加1 使用C语言风格的后缀自增 echo VAR 22 VAR乘以22并将结果送入命令 echo VAR 22 同上 但为过时用法 命令可以用于条件语句 因为它的退出状态是0或者非0 大多数情况下是1 可以用于是与非的条件判断 if VAR Y 3 X 2 then echo Yes fi Z gt 23 amp amp echo Yes 命令支持下列比较操作符 gt lt gt 和 lt bash不能在自身进程内进行浮点数运算 当前有这个能力的unix shell只有Korn shell和Z shell 输入输出重定向 编辑 bash拥有传统Bourne shell缺乏的I O重定向语法 bash可以同时重定向标准输出和标准错误 这需要使用下面的语法 command amp gt file 这比等价的Bourne shell语法 command gt file 2 gt amp 1 来的简单 2 05b版本以后 bash可以用下列语法重定向标准输入至字符串 称为here string command lt lt lt string to be read as standard input 如果字符串包括空格就需要用引号包裹字符串 例子 重定向标准输出至文件 写数据 关闭文件 重置标准输出 生成标准输出 文件描述符1 的拷贝文件描述符6 exec 6 gt amp 1 打开文件 test data 以供写入 exec 1 gt test data 产生一些内容 echo data data data 关闭文件 test data exec 1 gt amp 使标准输出指向FD 6 重置标准输出 exec 1 gt amp 6 关闭FD6 exec 6 gt amp 打开及关闭文件 打开文件test data以供读取 exec 6 lt test data 读文件直到文件尾 while read u 6 dta do echo dta done 关闭文件test data exec 6 lt amp 抓取外部命令的输出 运行 find 并且将结果存于VAR 搜索以 h 结尾的文件名 VAR find name h 进程内的正则表达式 编辑 bash 3 0支持进程内的正则表达式 使用下面的语法 string regex 正则表达式语法同regex 7 man page所描述的一致 正则表达式匹配字符串时上述命令的退出状态为0 不匹配为1 正则表达式中用圆括号括起的子表达式可以访问shell变量BASH REMATCH 如下 if abcfoobarbletch foo bar bl then echo The regex matches echo BASH REMATCH outputs foobarbletch echo BASH REMATCH 1 outputs bar echo BASH REMATCH 2 outputs etch fi 使用这个语法的性能要比生成一个新的进程来运行grep命令优越 因为正则表达式匹配在bash进程内完成 如果正则表达式或者字符串包括空格或者shell 关键字 诸如 或者 就需要用引号包裹 Bash 4 开始的版本已经不需要这么做了 转义字符 编辑 string 形式的字符串会被特殊处理 字符串会被展开成string 并像C语言那样将反斜杠及紧跟的字符进行替换 反斜杠转义序列的转换方式如下 转义字符 转义字符 扩展成 a 响铃符 b 退格符 e ANSI转义符 等价于 033 f 馈页符 n 换行符 r 回车符 t 水平制表符 v 垂直制表符 反斜杠 单引号 nnn 十进制值为nnn的8 bit字符 1 3位 xHH 十六进制值为HH的8 bit字符 1或2位 cx control X字符扩展后的结果将被单引号包裹 就好像美元符号一直就不存在一样 双引号包裹的字符串前若有一个美元符号 将会使得字符串被翻译成符合当前locale的语言 如果当前locale是C或者POSIX 美元符号会被忽略 如果字符串被翻译并替换 替换后的字符串仍被双引号包裹 关联数组 编辑Bash 4 0 开始支持关联数组 通过类似AWK的方式 对于多维数组提供了伪支持 declare A a 声明一个名为a的伪二位数组 i 1 j 2 a i j 5 将键 i j 与值 5 对应 echo a i j 移植性 编辑 调用Bash时指定 posix 或者在脚本中声明 set o posix 可以使得Bash几乎遵循 POSIX 1003 2 标准 若要保证一个Bash脚本的移植性 至少需要考虑到 Bourne shell 即Bash取代的shell Bash有一些传统的 Bourne shell 所没有的特性 包括以下这些 某些扩展的调用选项 命令替换 即 尽管这是 POSIX 1003 2 标准的一部分 花括号扩展 某些数组操作 关联数组 扩展的双层方括号判断语句 某些字符串生成操作 进程替换 正则表达式匹配符 Bash特有的内置工具 协进程键盘快捷键 编辑 Bash默认使用Emacs的快捷键 可以通过 set o vi 让它使用Vi的快捷键 进程管理 编辑 Bash有两种执行命令的模式 批处理模式 并发模式 批处理模式 编辑 要以 批处理模式 执行命令 即按照顺序 必须用 分隔 例子如下 command1 command2 在这个例子中 当command1执行完毕 即执行command2 并发模式 编辑使command1后台运行 则单独在结尾处使用 amp 例子如下 command1 amp 要并发执行两个命令 它们必须用 amp 分隔 例子如下 command1 amp command2 在这种情况下 command1 在后台执行 通过 amp 从而立即将控制返回到shell 以执行command2 通过 Control Z 可以将当前进程挂起 放置后台并暂停运行 可通过 fg 命令恢复至前台 也通过bg将挂起的进程后台运行 查看进程状态 编辑所有进程的情况 我们可以通过jobs命令查看 包含正在后台运行和停止了的 jobs 1 Running command1 amp 2 Stopped command2上例的输出结果中 中括号包围的数字 如 1 和 2 为job的ID号 加号 用于指定fg和bg命令的默认对象job 减号 用于指定 若当前的默认对象job退出后 下一个默认对象job是谁 Running 和 Stopped 表示进程状态 最后一个字段为命令 7 总结 一般命令在前台执行 fg 执行完毕后 控制返回给用户 在命令后面加上 amp 它会在后台执行 bg 并将特殊的环境变量 设置为该任务的进程ID 这时shell可以并发执行其他命令 后台程序试图写入数据到终端设备时 与写入标准输出不同 可能被阻塞 shell可以等待一个后台任务执行完成 只需使用wait命令 加上进程ID或者任务序号 也可以等待所有的后台任务 只需使用不加参数的wait启动脚本 编辑bash启动的时候会运行各种不同的脚本 当bash作为一个登录的交互shell被调用 或者作为非交互shell但带有 login参数被调用时 它首先读入并执行文件 etc profile 然后它会依次寻找 bash profile bash login 和 profile 读入并执行第一个存在且可读的文件 noprofile参数可以阻止bash启动时的这种行为 当一个登录shell退出时 bash读取并执行 bash logout文件 如果此文件存在 当一个交互的非登录shell启动后 bash读取并执行 bashrc文件 这个行为可以用 norc参数阻止 rcfile file参数强制bash读取并执行指定的file而不是默认的 bashrc 如果用sh来调用bash bash在启动后进入posix模式 它会尽可能模仿sh历史版本的启动行为 以便遵守POSIX标准 用sh名字调用的非交互shell不会去读取其他启动脚本 rcfile参数无效 当bash以POSIX模式启动时 例如带有 posix参数 它使用POSIX标准来读取启动文件 在此模式下 交互shells扩展变量ENV 从以此为文件名的文件中读取命令并执行 bash会探测自己是不是被远程shell守护程序运行 通常是rshd 如果是 它会读取并执行 bashrc中的命令 但是rshd一般不会用rc相关参数调用shell 也不会允许指定这些参数 Bash与Bourne shell和csh启动脚本的比较 编辑 Bash的特性是从Bourne shell和csh发展而来 因此一定程度上允许同Bourne shell的启动文件共享 并提供一些csh用户熟悉的启动特性 设置可继承的环境变量 编辑Bourne shell登陆时使用 profile 来设置环境变量 这些环境变量可以被子进程继承 Bash可以以兼容的方式使用 profile 只需在Bash自有的脚本中显式执行下面这行代码 通过在 profile 中避免使用Bash特有的语法 就可以和Bourne shell保持兼容性 profile 别名和函数 编辑更通用的函数以及借鉴自csh的 别名 alias 很大程度上取代了Bourne shell的别名 alias 和函数 然而这两个特性一般不能从登录式shell中继承 在该登录式shell的子shell中 它们必须被重新定义 尽管有个环境变量ENV可以被用于这个问题 不过 csh 和 Bash 都可以用子shell的启动脚本直接处理 在Bash当中 bashrc 是交互式子shell启动时执行的脚本 如果想要在登录式shell中使用 bashrc 定义的函数 可以在 bash login 的环境变量后面加上这样一行 bashrc 登录与登出时执行的命令 编辑最初登录时 csh 执行 login 可以执行一些只在登录时执行的操作 例如显示系统负载 硬盘状态 是否收到新邮件 在日志中记录登录时间 等等 Bourne shell 可以在 profile 文件中模拟这种行为 但并没有预先定义文件名 可以在 bash profile 文件的环境变量设置和函数定义的后面添加这样一行 bash login与之类似 csh还有一个文件 logout 这个文件只在登录式shell退出时执行 Bash与之对应的文件是 bash logout 并且不需要专门的设置 在 Bourne shell 中 trap 这个内置工具可以实现类似的效果 兼容旧环境的Bash启动脚本示例 编辑 下面这个 bash profile 的框架与 Bourne shell 兼容 并且为 bashrc 和 bash login 提供类似于 csh 的语义 r i 文件名 i 测试指定文件是否存在 如果不存在 跳过 amp amp 后面的部分 r profile amp amp profile 只使用Bourne shell的语法设置环境变量 if n PS1 then 判断是否是交互式shell r bashrc amp amp bashrc 加载 bashrc tty prompt 函数设置等 r bash login amp amp bash login 执行登录式shell登录时的任务 fi if块的结束标志 Bash 启动脚本与操作系统相关的问题 编辑 一些 Unix 和 Linux 版本常在 etc 放置 Bash 的系统级启动脚本 Bash在其标准的初始化过程中执行它们 不过其他启动脚本可以按照不同于Bash启动序列文档所述的顺序来读取这些文件 root 用户的文件默认内容 以及新用户被创建时系统提供的默认文件可能有问题 启动 X Window系统 的启动脚本可能使用用户的 Bash 启动脚本尝试在 窗口管理器 启动之前设置用户的环境变量 这些问题常常可以通过使用 xsession 或者 xprofile 来读取 profile 而解决 参见 编辑 nbsp 自由软件主题 Unix shell脚注 编辑 bash 5 2 21 tar gz 2023年11月9日 2023年11月9日 Bash FAQ version 4 14 2016 04 09 原始内容存档于2018 09 01 Why does Apple ship bash 3 2 apple stackexchange com 2019 04 25 原始内容存档于2016 04 16 Missing source code GPL compliance Issue 107 Microsoft WSL GitHub 2019 04 25 原始内容存档于2019 09 24 GNU Bash Softpedia SoftNews 2016 04 09 原始内容存档于2017 10 21 GNU Project README file 2019 04 25 原始内容存档于2019 04 26 Bash is free software distributed under the terms of the GNU General Public License as published by the Free Software Foundation version 3 of the License or any later version jobs 1p Linux manual page man7 org 2020 01 14 原始内容存档于2020 01 14 外部链接 编辑GNU Bash主页 GNU Bash在GNU的主页 页面存档备份 存于互联网档案馆 bashdb 页面存档备份 存于互联网档案馆 带有调试器的Bash Bash入门指南 页面存档备份 存于互联网档案馆 英文 Bash同标准unix shell的不同 页面存档备份 存于互联网档案馆 Bash by example 页面存档备份 存于互联网档案馆 Bash基础编程 取自 https zh wikipedia org w index php title Bash amp oldid 77816833, 维基百科,wiki,书籍,书籍,图书馆,

文章

,阅读,下载,免费,免费下载,mp3,视频,mp4,3gp, jpg,jpeg,gif,png,图片,音乐,歌曲,电影,书籍,游戏,游戏。