bash语法
来源:互联网 发布:可云的孩子是谁的 知乎 编辑:程序博客网 时间:2024/04/29 10:26
一、变量
1.1 变量的使用
- 变量的定义
variable=name
注意,=两边不能有空格。一切变量都会被视为字符串。如果要使用局部变量则要加关键字local。
- 输出变量的值
echo ${variable}
其实这是参数和变量扩展。关于echo的详细用法在下面章节。
- 删除变量
unset variable
注意,不能在变量前加$。
- 将变量转化为全局的环境变量:
export variable
同样不能加$。环境变量将在子Shell中可见,但是当前Shell的环境变量不会影响父Shell。
1.2 环境变量
环境变量存储了有关Shell会话和工作环境的信息。一般情况下,用户登录成功后,会启动其Shell,这个Shell叫做登录Shell。这个Shell自带一些全局的环境变量,并且它会运行相应的配置文件,初始化部分环境变量。所以当我们要定义一些自己的变量时就要定义在这些配置文件中,这样启动时便会定义了这些环境变量。另外环境变量在Shell脚本中是可以直接引用的。下面讲解会运行脚本。
登录Shell:
可以发现,用户的当前目录下的三个隐藏的配置文件有优先级,且且只读取第一个找到的配置文件。这里先看下全局配置文件。
1.3 全局配置文件/etc/profile
# /etc/profile: system-wide .profile file for the Bourne shell (sh(1))# and Bourne compatible shells (bash(1), ksh(1), ash(1), ...).if [ "$PS1" ]; then if [ "$BASH" ] && [ "$BASH" != "/bin/sh" ]; then # The file bash.bashrc already sets the default PS1. # PS1='\h:\w\$ ' if [ -f /etc/bash.bashrc ]; then . /etc/bash.bashrc fi else if [ "`id -u`" -eq 0 ]; then PS1='# ' else PS1='$ ' fi fifi# The default umask is now handled by pam_umask.# See pam_umask(8) and /etc/login.defs.if [ -d /etc/profile.d ]; then for i in /etc/profile.d/*.sh; do if [ -r $i ]; then . $i fi done unset ifiexport JAVA_HOME=/usr/lib/jvm/jdk1.8.0_45export CLASSPATH=.:$JAVA_HOME/libexport MYSQL_HOME=/usr/local/mysqlexport CATALINA_BASE=/opt/apache-tomcat-8.0.28export CATALINA_HOME=/opt/apache-tomcat-8.0.28export TOMCAT_HOME=/opt/apache-tomcat-8.0.28export SQLITE_HOME=/home/gzx/sqlite3export M2_HOME=/home/gzx/apache-maven-3.3.9export PATH=$JAVA_HOME/bin:$MYSQL_HOME/bin:$TOMCAT_HOME/bin:$SQLITE_HOME/bin:$M2_HOME/bin:$PATH
这个文件是所有用户公用的,所以定义在这里的环境变量所有用户Shell都有效。
在上面的脚本中,在PS1变量存在的情况下,判断是否已经有BASH这个环境变量,而且该环境变量不是/bin/sh,则在当前Shell执行存在的文件/etc/bash.bashrc(这个文件的内容在下一部分解释)。否则设置PS1:对于超级用户,则PS1为#,对于普通用户则为$。本人是第一种情况。
接着执行/etc/profile.d下的sh脚本,最后导出一些自定义的全局环境变量。/etc/profile.d目录下可以自定义一些脚本。
1.4 用户自定义配置.profile
在本人的用户目录下,只有一个.profile文件。
# ~/.profile: executed by the command interpreter for login shells.# This file is not read by bash(1), if ~/.bash_profile or ~/.bash_login# exists.# see /usr/share/doc/bash/examples/startup-files for examples.# the files are located in the bash-doc package.# the default umask is set in /etc/profile; for setting the umask# for ssh logins, install and configure the libpam-umask package.#umask 022# if running bashif [ -n "$BASH_VERSION" ]; then # include .bashrc if it exists if [ -f "$HOME/.bashrc" ]; then . "$HOME/.bashrc" fifi# set PATH so it includes user's private bin if it existsif [ -d "$HOME/bin" ] ; then PATH="$HOME/bin:$PATH"fi
在BASH_VERSION变量非空且~/.bashrc存在的情况下,执行该脚本。本人的机子会执行该脚本(留到下一节)。如果~/bin目录存在,则将该目录加到PATH环境变量中。
1.5 交互式Shell
当我们在桌面系统中打开一个伪模拟终端时,会启动一个交互式bash。这个bash也会执行配置文件/etc/bash.bashrc和~/.bashrc。而这两个文件刚好也会在登录Shell中执行。
/etc/bash.bashrc这个文件基本没做什么。
# System-wide .bashrc file for interactive bash(1) shells.# To enable the settings / commands in this file for login shells as well,# this file has to be sourced in /etc/profile.# If not running interactively, don't do anything[ -z "$PS1" ] && return# check the window size after each command and, if necessary,# update the values of LINES and COLUMNS.shopt -s checkwinsize# set variable identifying the chroot you work in (used in the prompt below)if [ -z "${debian_chroot:-}" ] && [ -r /etc/debian_chroot ]; then debian_chroot=$(cat /etc/debian_chroot)fi# set a fancy prompt (non-color, overwrite the one in /etc/profile)PS1='${debian_chroot:+($debian_chroot)}\u@\h:\w\$ '# Commented out, don't overwrite xterm -T "title" -n "icontitle" by default.# If this is an xterm set the title to user@host:dir#case "$TERM" in#xterm*|rxvt*)# PROMPT_COMMAND='echo -ne "\033]0;${USER}@${HOSTNAME}: ${PWD}\007"'# ;;#*)# ;;#esac# enable bash completion in interactive shells#if ! shopt -oq posix; then# if [ -f /usr/share/bash-completion/bash_completion ]; then# . /usr/share/bash-completion/bash_completion# elif [ -f /etc/bash_completion ]; then# . /etc/bash_completion# fi#fi# sudo hintif [ ! -e "$HOME/.sudo_as_admin_successful" ] && [ ! -e "$HOME/.hushlogin" ] ; then case " $(groups) " in *\ admin\ *|*\ sudo\ *) if [ -x /usr/bin/sudo ]; then cat <<-EOF To run a command as administrator (user "root"), use "sudo <command>". See "man sudo_root" for details. EOF fi esacfi# if the command-not-found package is installed, use itif [ -x /usr/lib/command-not-found -o -x /usr/share/command-not-found/command-not-found ]; then function command_not_found_handle { # check because c-n-f could've been removed in the meantime if [ -x /usr/lib/command-not-found ]; then /usr/lib/command-not-found -- "$1" return $? elif [ -x /usr/share/command-not-found/command-not-found ]; then /usr/share/command-not-found/command-not-found -- "$1" return $? else printf "%s: command not found\n" "$1" >&2 return 127 fi }fi
最后再看下.bashrc这个配置文件。
# ~/.bashrc: executed by bash(1) for non-login shells.# see /usr/share/doc/bash/examples/startup-files (in the package bash-doc)# for examples# If not running interactively, don't do anythingcase $- in *i*) ;; *) return;;esac# don't put duplicate lines or lines starting with space in the history.# See bash(1) for more optionsHISTCONTROL=ignoreboth# append to the history file, don't overwrite itshopt -s histappend# for setting history length see HISTSIZE and HISTFILESIZE in bash(1)HISTSIZE=1000HISTFILESIZE=2000# check the window size after each command and, if necessary,# update the values of LINES and COLUMNS.shopt -s checkwinsize# If set, the pattern "**" used in a pathname expansion context will# match all files and zero or more directories and subdirectories.#shopt -s globstar# make less more friendly for non-text input files, see lesspipe(1)[ -x /usr/bin/lesspipe ] && eval "$(SHELL=/bin/sh lesspipe)"# set variable identifying the chroot you work in (used in the prompt below)if [ -z "${debian_chroot:-}" ] && [ -r /etc/debian_chroot ]; then debian_chroot=$(cat /etc/debian_chroot)fi# set a fancy prompt (non-color, unless we know we "want" color)case "$TERM" in xterm-color) color_prompt=yes;;esac# uncomment for a colored prompt, if the terminal has the capability; turned# off by default to not distract the user: the focus in a terminal window# should be on the output of commands, not on the prompt#force_color_prompt=yesif [ -n "$force_color_prompt" ]; then if [ -x /usr/bin/tput ] && tput setaf 1 >&/dev/null; then # We have color support; assume it's compliant with Ecma-48 # (ISO/IEC-6429). (Lack of such support is extremely rare, and such # a case would tend to support setf rather than setaf.) color_prompt=yes else color_prompt= fifiif [ "$color_prompt" = yes ]; then PS1='${debian_chroot:+($debian_chroot)}\[\033[01;32m\]\u@\h\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]\$ 'else PS1='${debian_chroot:+($debian_chroot)}\u@\h:\w\$ 'fiunset color_prompt force_color_prompt# If this is an xterm set the title to user@host:dircase "$TERM" inxterm*|rxvt*) PS1="\[\e]0;${debian_chroot:+($debian_chroot)}\u@\h: \w\a\]$PS1" ;;*) ;;esac# enable color support of ls and also add handy aliasesif [ -x /usr/bin/dircolors ]; then test -r ~/.dircolors && eval "$(dircolors -b ~/.dircolors)" || eval "$(dircolors -b)" alias ls='ls --color=auto' #alias dir='dir --color=auto' #alias vdir='vdir --color=auto' alias grep='grep --color=auto' alias fgrep='fgrep --color=auto' alias egrep='egrep --color=auto'fi# colored GCC warnings and errors#export GCC_COLORS='error=01;31:warning=01;35:note=01;36:caret=01;32:locus=01:quote=01'# some more ls aliasesalias ll='ls -alF'alias la='ls -A'alias l='ls -CF'# Add an "alert" alias for long running commands. Use like so:# sleep 10; alertalias alert='notify-send --urgency=low -i "$([ $? = 0 ] && echo terminal || echo error)" "$(history|tail -n1|sed -e '\''s/^\s*[0-9]\+\s*//;s/[;&|]\s*alert$//'\'')"'# Alias definitions.# You may want to put all your additions into a separate file like# ~/.bash_aliases, instead of adding them here directly.# See /usr/share/doc/bash-doc/examples in the bash-doc package.if [ -f ~/.bash_aliases ]; then . ~/.bash_aliasesfi# enable programmable completion features (you don't need to enable# this, if it's already enabled in /etc/bash.bashrc and /etc/profile# sources /etc/bash.bashrc).if ! shopt -oq posix; then if [ -f /usr/share/bash-completion/bash_completion ]; then . /usr/share/bash-completion/bash_completion elif [ -f /etc/bash_completion ]; then . /etc/bash_completion fifiunset JAVA_TOOL_OPTIONSfunction factorial { if [ $1 -eq 1 ] then echo 1 else local tmp=$[ $1 - 1 ] local res=`factorial $tmp` local ret=$[ $res * $1 ] echo $ret fi}PATH=.:$PATH
显然,这个文件只能在交互式启动时才能执行。会初始化历史记录的长度变量HISTSIZE。同时定义了一些命令的别名,如ls、grep会自动显示颜色。ll和l都是命令别名。最后自己定义了一个递归的阶乘函数factorial,以及在PATH前面追加一个当前目录。这个配置文件用于存放用户的一些自定义的脚本。如果在交互式Shell再运行bash,则会再次运行.bashrc。对于脚本,其运行时的Shell在最开头定义#!/bin/bash,这是非交互式Shell,一般不会运行任何配置文件。
1.6 重要的环境变量
二、数组
- 定义一个数组
array=(hello world you are 212)
数组元素用空格隔开,而不是用逗号。
- 访问某一项
echo ${array[1]}
注意,对于数组要加花括号。第0项有两种输出方法:
echo ${array[0]}echo $array
- 输出整个数组
echo "${array[@]}"
也可以用循环语句逐项输出。
- 输出数组的长度
echo ${#array[@]}
注意,未初始化的元素不会参与计数。这与其他语言不同。
- 追加元素
array+=(d e f)
注意+=不能出现空格。
- 数组排序
array_sorted=$(for i in "${array[@]}"; do echo $i; done | sort)
注意sort排序使用的是本地化设置,小写字母会出现在大写字母前面。
三、结构化命令
下面的list表示的是命令、test命令、复合命令[[]]、复合命令(()),以及用&&、||等连接上述命令的表达式。
- 条件语句
if list; then cmd1elif list; then cmd2else cmd3fi
注意,使用方法和C语言类似。list命令执行成功则会执行对应的语句。
- case 语句
case variable inpattern1 | pttern2) cmd1;;pattern3 | pattern4) cmd2;;*) cmd3;;esac
注意上面要用;;结束,表示当前项匹配时,不会继续往下匹配。最后要用case反过来写的esac结束。对于每一项,可以使用|来提供相同命令的执行。最后一项是默认。这里的pattern和路径名匹配类似。
- for语句
for variable in word; do cmddone
这里的word可以是一个字符串,或者是一个命令的执行结果,即命令替换,或者数组(一般要用引号包围),但是用$IFS分割。cmd使用variable时必须加$,因为它是一个变量。另外这个命令还可以直接输出或者重定向,即在done后加>或者|,将for的输出重定向,或者通过管道输出。
for (( expr1; expr2; expr3 )); do cmddone
这是一种C语言风格的for语句,用法跟C语言类似。但是expr必须是算术表达式,不用加(()),可以加任意空格。
- while语句
while list; do cmddone
跟C语言类似。只要list成立,则不断循环。
- until语句
until list; do cmddone
这个语句表示当list成立时,退出循环。与while的语义正好相反。while和until语句都可以使用break和continue这两个控制命令,与C语言用法类似。
四、条件表达式
4.1 test命令
test命令的格式如下:
test expression
但是我们更常用它的等价命令:
[expression]
expression可以分为三类,分别是数值比较、字符串比较、文件比较。其中数值比较可以使用算术表达式(())替代。而test命令也有更高级更新的形式[[]]复合命令,它还支持字符串模式匹配。
- 数值比较
arg1 OP arg2
这里arg是数值,而OP是-eq, -ge, -gt, le, -lt, -ne。
- 字符串比较
#字符串长度非空-n string#字符串长度为空-z string#字符串相等,[[]]还可以用==,同时它还支持模式匹配string1 = string2string1 != string2#使用ASCII排序。对于test命令必须用\对<和>转义,[[]]不用。string1 < string2string1 > string2
- 文件比较
#文件是否存在-e file#文件存在且是目录-d file#文件存在且是普通文件-f file#文件存在且可读-r file#文件存在且可写-w file#文件存在且可执行-x file#文件更新,file2可以不存在file1 -nt file2#文件更老,file1可以不存在file1 -ot file2
4.2 算术表达式(())
格式是
$((expression))
其中$可以省略。算术表达式专门用于数值运算。expression如下,优先级相同的放在一组,同时优先级从上到下递减。
id++ id-- ++id --id - + #正负号 ! ~ #逻辑取反和位取反 ** #幂运算 * / % #乘除取余 + - #加减 << >> #左右位移 <= >= < > #比较 == != #相等和不等 & #按位与 ^ #按位异或 | #按位或 && #逻辑与 || #逻辑或 expr?expr:expr = *= /= %= += -= <<= >>= &= ^= |= expr1 , expr2 #逗号表达式
五、字符串
#字符串长度${#parameter}#从offset开始的length个字符${parameter:offset:length}#从头开始去除最短匹配${parameter#pattern}#从开头开始去除最长匹配${parameter##pattern}#从尾开始去除最短匹配${paramter%pattern}#从尾开始去除最长匹配${parameter%%pattern}#从头替换第一个字符串${paramter/pattern/string}${paramter/#pattern/string}#从尾替换第一个字符串${paramter/%pattern/string}#替换全部匹配的字符串${parameter//pattern/string}
注意,当没有给出string时,将删除pattern。
六、输入
6.1 read命令
read的格式如下:
read -t timeout -p prompt -s var1 var2 var3...
read将使用$IFS对输入的一行进行分割,以换行符作为读入结束的标志。其中,-t表示等待多少秒,超时没有输入则返回。-p输出提示字符。-s表示输入不回显,一般在输入密码时使用。后面的var1表示接收的变量名。read将分割的第一项给var1,第二项给var2,第三项给var3。对于多出的项全部给最后一项,对于少的置空。如果没有给出任何参数,则默认给变量$REPLY。
由于这个命令是一行一行处理,所以可以用于处理文件。不过它不支持从管道读取。
6.2 here文档
格式如下:
cat <<- _EOF_str_EOF_
<<-后面的-表示忽略开始的tab,这样_EOF_就不用顶格写。_EOF_用于表示输入的起始和结束。
6.3 here字符串
cat <<< word
七、输出
7.1 回显echo
默认情况下,echo会输出一个换行符号。如果不要输出换行符号,则必须加-n选项:
echo -n ${variable}
如果要对转移字符进行解释,如\n,则必须加-e选项:
echo -e ${variable}
7.2 格式化输出printf
这是格式化输出语句,默认不会有换行,和C语言用法基本一致。
printf format var1 var2 ...
注意,后面的变量要加$。
八、函数
函数的格式:
function func_name(){}
这里funciton关键字和括号可以省略其中一个。因为这里的函数的参数不会通过括号里给出,而且传递的参数的个数是任意的,所以括号没什么必要。那么在函数内部这些传递的参数是怎么获取到的呢?这是通过位置参数来获取的。
位置参数的格式是$1, …, $9, ${10}, ${11}…。注意大于9的位置参数要加花括号,而且参数是从1开始算起的。另外,$0表示的脚本文件的名字,$#表示位置参数的个数。不仅可以给函数传递参数,还可以给脚本传递参数,而且获取的都是这些位置参数。获取所有参数的变量是”$@”。
另外shift可以将位置参数整体往前移动一位,所以在有shift的while循环中,每次只需判断和利用\$1就可以了。
九、信号
脚本中可以设置信号句柄,格式是:
trap cmd[func_handler] signal_name...
其中,第一个参数命令后者函数句柄,第二个参数是信号的名字或者信号号码。如SIGINT,SIGTERM。
十、运行脚本
10.1 手动运行
对于首行没有#!/bin/bash的且没有可执行权限的文件,可以在当前Shell运行:
source filename. filename
对于一般的文件,则要在首行添加#!/bin/bash,并修改可执行权限。
chmod u+x filename
运行时脚本的目录必须在PATH目录下,或者当前目录.在PATH目录下,这样可以直接用文件名运行。
filename
最后一种方法,可以直接用完整路径名运行。
#脚本在当前工作目录中./filename#任意目录full direcory/filename
10.2 自动运行
主要有两种方式,一种是在将自己的脚本写在/etc/rc.local里面,这样开机时init会创建该进程。另一种是在/etc/profile.d下放置自己的sh脚本,这样用户登录时会执行。或者在~/.bashrc中定义自己的脚本,每次打开一个交互式终端,都会执行。
10.3 在非控制台下运行
当控制终端会话退出时,会收到一个SIGHUP信号,这时所有在这个终端上的进程都会被终止。如果要使进程能够继续运行,则必须屏蔽该信号,即
nohup script &
但该脚本的输出将导出到脚本所在目录下的nohup.out中。
- bash语法
- BASH 语法
- bash语法
- bash流程操作语法
- bash 语法 小结
- BASH 的基本语法
- bash (2) 基本语法
- BASH语法详解
- bash的诡异语法
- bash的诡异语法.
- BASH 的基本语法
- 转载:bash 语法
- bash shell while语法
- Shell bash 脚本语法
- Bash 基本语法
- BASH 的基本语法
- bash 语法 小结
- BASH 的基本语法
- 画面表示時にFocusを付けたくないとき
- AFNetworking源码 - Multipart协议,AFURLRequestSerialization和AFURLResponseSerialization
- 双向队列
- SFDC:Comparable Interfaceについて
- AFNetworking源码 - AFSecurityPolicy 和 AFNetworkReachabilityManager
- bash语法
- 1118_数制转换
- CSS3圆角
- 关于PagerAdapter、FragmentPagerAdapter、FragmentStatePageradapter之间的区别
- unity3D 在UGUI中模拟NGUI的spine with mouse
- uva11094
- Linux CentOS 6.5中安装与配置Tomcat-8方法
- angular创建新指令directive中scope的作用以及绑定策略
- Git和GitHub的使用方法