首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >SHELL(bash)脚本编程二:语法

SHELL(bash)脚本编程二:语法

作者头像
用户5030870
发布于 2019-04-11 02:55:56
发布于 2019-04-11 02:55:56
1.5K00
代码可运行
举报
文章被收录于专栏:self_studyself_study
运行总次数:0
代码可运行

本文开始正式介绍shell脚本的编写方法以及bash的语法。

定义

元字符 用来分隔词(token)的单个字符,包括:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
|  & ; ( ) < > space tab

token 是指被shell看成一个单一单元的字符序列 bash中包含三种基本的token:保留关键字操作符单词保留关键字是指在shell中有明确含义的词语,通常用来表达程序控制结构。包括:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
! case coproc do done elif else esac fi for function if in select then until while { } time [[ ]]

操作符由一个或多个元字符组成,其中控制操作符包括:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
|| & && ; ;; ( ) | |& <newline>

余下的shell输入都可以视为普通的单词(word)。

shell脚本是指包含若干shell命令的文本文件,标准的bash脚本的第一行形如#!/bin/bash,其中顶格写的字符#!向操作系统申明此文件是一个脚本,紧随其后的/bin/bash是此脚本程序的解释器,解释器可以带一个选项(选项一般是为了对一些情况做特殊处理,比如-x表示开启bash的调试模式)。 除首行外,其余行中以符号#开头的单词及本行中此单词之后的字符将作为注释,被解析器所忽略。

语法

相比于其他更正式的语言,bash的语法较为简单。大多数使用bash的人员,一般都先拥有其他语言的语法基础,在接触bash的语法之后,会自然的将原有语法习惯套用到bash中来。事实上,bash的语法灵活多变,许多看起来像是固定格式的地方,实际上并不是。这让一些初学者觉得bash语法混乱不堪,复杂难记。这和bash的目的和使用者使用bash的目的有很大的关系,bash本身是为了提供一个接口,来支持用户通过命令与操作系统进行交互。用户使用bash,一般是为了完成某种系统管理的任务,而不是为了做一款独立的软件。这些,都使人难以像学习其他编程语言那样对bash认真对待。其实,只要系统学习一遍bash语法以及一条命令的执行流程,就可以说掌握了bash脚本编程的绝大多数内容。 bash语法只包括六种:简单命令管道命令序列命令复合命令协进程命令(bash版本4.0及以上)和函数定义

简单命令

shell简单命令(Simple Commands)包括命令名称,可选数目的参数和重定向(redirection)。我们在Linux基础命令介绍系列里所使用的绝大多数命令都是简单命令。另外,在命令名称前也可以有若干个变量赋值语句(如上一篇所述,这些变量赋值将作为命令的临时环境变量被使用,后面有例子)。简单命令以上述控制操作符为结尾。 shell命令执行后均有返回值(会赋给特殊变量$?),是范围为0-255的数字。返回值为0,表示命令执行成功;非0,表示命令执行失败。(可以使用命令echo $?来查看前一条命令是否执行成功)

管道命令

管道命令(pipeline)是指被||&分隔的一到多个命令。格式为:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
[time [-p]] [ ! ] command1 [ | command2 ... ]

其中保留关键字time作用于管道命令表示当命令执行完成后输出消耗时间(包括用户态和内核态占用时间),选项-p可以指定时间格式。 默认情况下,管道命令的返回值是最后一个命令的返回值,为0,表示true,非0,则表示false;当保留关键字!作用于管道命令时,会对管道命令的返回值进行取反。 之前我们介绍过管道的基本用法,表示将command1的标准输出通过管道连接至command2的标准输入,这个连接要先于命令的其他重定向操作(试对比>/dev/null 2>&12>&1 >/dev/null的区别)。如果使用|&,则表示将command1的标准输出和标准错误都连接至管道。 管道两侧的命令均在子shell(subshell)中执行,这里需要注意:在子shell中对变量进行赋值时,父shell是不可见的。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#例如
[root@centos7 ~]# echo 12345|read NUM
[root@centos7 ~]# echo $NUM
                    #由于echo和read命令均在子shell中执行,所以当执行完毕时,在父shell中输出变量的值为空
[root@centos7 ~]# 

序列命令

序列命令(list)是指被控制操作符;,&,&&||分隔的一到多个管道命令,以;&<newline>为结束。 在这些控制操作符中,&&||有相同的优先级,然后是;&(也是相同的优先级)。 如果命令以&为结尾,此命令会在一个子shell中后台执行,当前shell不会等待此命令执行结束,并且不论它是否执行成功,其返回值均为0。 以符号;分隔的命令按顺序执行(和换行符的作用几乎相同),shell等待每个命令执行完成,它们的返回值是最后一个命令的返回值。 以符号&&||连接的两个命令存在逻辑关系。 command1 && command2:先执行command1,当且仅当command1的返回值为0,才执行command2。 command1 || command2:先执行command1,当且仅当command1的返回值非0,才执行command2。 脚本举例:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
    #!/bin/bash
    #简单命令
    echo $PATH > file
    #管道命令
    cat file|tr ':' ' '
    #序列命令
    IFS=':' read -a ARRAY <file && echo ${ARRAY[4]} || echo "赋值失败"
    echo "命令返回值为:$?。"
    #验证变量的临时作用域
    echo "$IFS"|sed 'N;s/[ \t\n]/-/g'

执行结果(在脚本所在目录直接执行./test.sh):

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
[root@centos7 ~]# ./test.sh   
/usr/local/sbin /usr/local/bin /usr/sbin /usr/bin /root/bin
/root/bin
命令返回值为:0---
[root@centos7 ~]# 

注意例子中序列命令的写法,其中IFS=':'只临时对内置命令read起作用(作为单词分隔符来分隔read的输入),read命令结束后,IFS又恢复到原来的值:$' \d\n'。 &&||在这里类似于分支语句,read命令执行成功则执行输出数组的第五个元素,否则执行输出"赋值失败"。

复合命令

1、(list)

list将在subshell中执行(注意赋值语句和内置命令修改shell状态不能影响当父shell),返回值是list的返回值。 此复合命令前如果使用扩展符$,shell称之为命令替换(另一种写法为`list`)。shell会把命令的输出作为命令替换扩展之后的结果使用。 命令替换可以嵌套。

2、{ list; }

list将在当前shell环境中执行,必须以换行或分号为结尾(即使只有一个命令)。注意不同于shell元字符(){}是shell的保留关键字,因为保留关键字不能分隔单词,所以它们和list之间必须有空白字符或其他shell元字符。

3、((expression))

expression是数学表达式(类似C语言的数学表达式),如果表达式的值非0,则此复合命令的返回值为0;如果表达式的值为0,则此复合命令的返回值为1。 此种复合命令和使用内置命令let "expression"是一样的。 数学表达式中支持如下操作符,操作符的优先级,结合性,计算方法都和C语言一致(按优先级从上到下递减排列):

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
id++ id--       # 变量后自加 后自减
++id --id       # 变量前自加 前自减
- +             # 一元减 一元加
! ~             # 逻辑否定 位否定
**              # 乘方
* / %           # 乘 除 取余
+ -             # 加 减
<< >>           # 左位移 右位移
<= >= < >       # 比较大小
== !=           # 等于 不等于
&               # 按位与
^               # 按位异或
|               # 按位或
&&              # 逻辑与
||              # 逻辑或
expr?expr:expr  # 条件表达式
= *= /= %= += -= <<= >>= &= ^= |=   # 赋值表达式
expr1 , expr2   # 逗号表达式

在数学表达式中,可以使用变量作为操作数,变量扩展要先于表达式的求值。变量还可以省略扩展符号$,如果变量的值为空或非数字和运算符的其他字符串,将使用0代替它的值做数学运算。 以0开头的数字将被解释为八进制数,以0x0X开头的数字将被解释为十六进制数。其他情况下,数字的格式可以是[base#]n。可选的base#表示后面的数字n是以base(范围是2-64)为基的数字,如2#11011表示11011是一个二进制数字,命令((2#11011))的作用会使二进制数转化为十进制数。如果base#省略,则表示数字以10为基。 复合命令((expression))并不会输出表达式的结果,如果需要得到结果,需使用扩展符$表示数学扩展(另一种写法为$[expression])。数学扩展也可以嵌套。 括号()可以改变表达式的优先级。

脚本举例:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#!/bin/bash
# (list)
(ls|wc -l)
#命令替换并赋值给数组 注意区分数组赋值array=(...)和命令替换$(...)
array=($(seq 10 10 $(ls|wc -l) | sed -z 's/\n/ /g'))
#数组取值
echo "${array[*]}"
# { list; }
#将文件file1中的第一行写入file2,{ list; } 是一个整体。
{ read line;echo $line;} >file2 <file1
#数学扩展
A=$(wc -c file2 |cut -b1)
#此时变量A的值为5
B=4
echo $((A+B))
echo $(((A*B)**2))
#赋值并输出
echo $((A|=$B))
#条件运算符 此命令意为:判断表达式A>=7是否为真,如果为真则计算A-1,否则计算(B<<1)+3。然后将返回结果与A作异或运算并赋值给A
((A^=A>=7?A-1:(B<<1)+3))
echo $A

执行结果:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
[root@centos7 temp]# ./test.sh 
43
10 20 30 40
9
400
5
14

4、[[ expression ]]

此处的expression是条件表达式(并非数学扩展中的条件表达式)。此种命令的返回值取决于条件表达式的结果,结果为true,则返回值为0,结果为false,则返回值为1。 条件表达式除可以用在复合命令中外,还可以用于内置命令test[,由于test[[]][]是内置命令或保留关键字,所以同保留关键字{}一样,它们与表达式之间都要有空格或其他shell元字符。 条件表达式的格式包括:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
-b file             #判断文件是否为块设备文件
-c file             #判断文件是否为字符设备文件
-d file             #判断文件是否为目录
-e file             #判断文件是否存在
-f file             #判断文件是否为普通文件
-g file             #判断文件是否设置了SGID
-h file             #判断文件是否为符号链接
-p file             #判断文件是否为命名管道文件
-r file             #判断文件是否可读
-s file             #判断文件是否存在且内容不为空(也可以是目录)
-t fd               #判断文件描述符fd是否开启且指向终端
-u file             #判断文件是否设置SUID
-w file             #判断文件是否可写
-x file             #判断文件是否可执行
-S file             #判断文件是否为socket文件
file1 -nt file2     #判断文件file1是否比file2更新(根据mtime),或者判断file1存在但file2不存在
file1 -ot file2     #判断文件file1是否比file2更旧,或者判断file2存在但file1不存在
file1 -ef file2     #判断文件file1和file2是否互为硬链接
-v name             #判断变量状态是否为set(见上一篇)
-z string           #判断字符串是否为空
-n string           #判断字符串是否非空
string1 == string2  #判断字符串是否相等
string1 = string2   #判断字符串是否相等
string1 != string2  #判断字符串是否不相等
string1 < string2   #判断字符串string1是否小于字符串string2(字典排序),用于内置命令test中时,小于号需要转义:\<
string1 > string2   #判断字符串string1是否大于字符串string2(字典排序),用于内置命令test中时,大于号需要转义:\>
NUM1 -eq NUM2       #判断数字是否相等
NUM1 -ne NUM2       #判断数字是否不相等
NUM1 -lt NUM2       #判断数字NUM1是否小于数字NUM2
NUM1 -le NUM2       #判断数字NUM1是否小于等于数字NUM2
NUM1 -gt NUM2       #判断数字NUM1是否大于数字NUM2
NUM1 -ge NUM2       #判断数字NUM1是否大于等于数字NUM2

[[ expr ]][ expr ](test expr[ expr ]的另一种写法,效果相同)还接受如下操作符(从上到下优先级递减):

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
! expr    #表示对表达式expr取反
( expr )  #表示提高expr的优先级
expr1 -a expr2  #表示对两个表达式进行逻辑与操作,只能用于 [ expr ] 和 test expr 中
expr1 && expr2  #表示对两个表达式进行逻辑与操作,只能用于 [[ expr ]] 中
expr1 -o expr2  #表示对两个表达式进行逻辑或操作,只能用于 [ expr ] 和 test expr 中
expr1 || expr2  #表示对两个表达式进行逻辑或操作,只能用于 [[ expr ]]

在使用操作符==!=判断字符串是否相等时,在[[ expr ]]中等号右边的string2可以被视为模式匹配string1,规则和通配符匹配一致。([ expr ]不支持) [[ expr ]]中比较两个字符串时还可以用操作符=~,符号右边的string2可以被视为是正则表达式匹配string1,如果匹配,返回真,否则返回假。

5、if list; then list; [ elif list; then list; ] ... [ else list; ] fi

条件分支命令。首先判断if后面的list的返回值,如果为0,则执行then后面的list;如果非0,则继续判断elif后面的list的返回值,如果为0,则......,若返回值均非0,则最终执行else后的list。fi是条件分支的结束词。 注意这里的list均是命令,由于要判断返回值,通常使用上述条件表达式来进行判断 形如:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
if [ expr ]
then
    list
elif [ expr ]
then
    list
...
else
    list
fi

甚至,许多人认为这样就是if语句的固定格式,其实if后面可以是任何shell命令,只要能够判断此命令的返回值。如:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
[root@centos7 ~]# if bash;then echo true;else echo false;fi
[root@centos7 ~]#   #执行后没有任何输出
[root@centos7 ~]# exit
exit
true                #由于执行了bash命令开启了一个新的shell,所以执行exit之后if语句才获得返回值,并做了判断和输出
[root@centos7 ~]# 

脚本举例:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#!/bin/bash
#条件表达式
declare A
#判断变量A是否set
[[ -v A ]] && echo "var A is set" || echo "var A is unset"
#判断变量A的值是否为空
[ ! $A ] && echo false || echo true
test -z $A && echo "var A is empty"
#通配与正则
A="1234567890abcdeABCDE"
B='[0-9]*'
C='[0-9]{10}\w+'
[[ $A = $B ]] && echo '变量A匹配通配符[0-9]*' || echo '变量A不匹配通配符[0-9]*'
[ $A == $B ] && echo '[ expr ]中能够使用通配符' || echo '[ expr ]中不能使用通配符'
[[ $A =~ $C ]] && echo '变量A匹配正则[0-9]{10}\w+' || echo '变量A不匹配正则[0-9]{10}\w+'
#if语句
# 此例并没有什么特殊的意义,只为说明几点需要注意的地方:
# 1if后面可以是任何能够判断返回值的命令
# 2、直接执行复合命令((...))没有输出,要取得表达式的值必须通过数学扩展 $((...))
# 3、复合命令((...))中表达式的值非0,返回值才是0
number=1
if  if test -n $A
    then
        ((number+1))
    else
        ((number-1))
    fi
then
    echo "数学表达式值非0,返回值为0"
else
    echo "数学表达式值为0,返回值非0"
fi
# if语句和控制操作符 && || 连接的命令非常相似,但要注意它们之间细微的差别:
# if语句中then后面的命令不会影响else后的命令的执行
# 但&&后的命令会影响||后的命令的执行
echo '---------------'
if [[ -r file && ! -d file ]];then
    grep -q hello file
else
    awk '/world/' file
fi
echo '---------------'
# 上面的if语句无输出,但下面的命令有输出
[ -r file -a ! -d file ] && grep -q hello file || awk '/world/' file
# 可以将控制操作符连接的命令写成这样来忽略&&后命令的影响(使用了内置命令true来返回真):
echo '---------------'
[ -r file -a ! -d file ] && (grep -q hello file;true) || awk '/world/' file

6、for name [[ in [ word ... ] ];]do list;done

7、for ((expr1;expr2;expr3));do list;done

bash中的for循环语句支持如上两种格式,在第一种格式中,先将in后面的word进行扩展,然后将得到的单词列表逐一赋值给变量name,每一次赋值都执行一次do后面的list,直到列表为空。如果in word被省略,则将位置变量逐一赋值给name并执行list。第二种格式中,双圆括号内都是数学表达式,先计算expr1,然后反复计算expr2,直到其值为0。每一次计算expr2得到非0值,执行do后面的list和第三个表达式expr3。如果任何一个表达式省略,则表示其值为1。for语句的返回值是执行最后一个list的返回值。

脚本举例:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#!/bin/bash
# word举例
for i in ${a:=3} $(head -1 /etc/passwd) $((a+=2))
do
    echo -n "$i "
done
echo $a
# 省略 in word
declare -a array
for number
do
    array+=($number)
done
echo ${array[@]}
# 数学表达式格式
for((i=0;i<${#array[*]};i++))
do
    echo -n "${array[$i]} "|sed 'y/1234567890/abcdefghij/'
done;echo

执行:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
[root@centos7 temp]# ./test.sh "$(seq 10)"   # 注意此处"$(seq 10)"将作为一个整体赋值给$1,如果去掉双引号将会扩展成10个值并赋给 $1 $2 ... ${10}
3 root:x:0:0:root:/root:/bin/bash 5 5        # 是否带双引号并不影响执行结果,只影响第二个for语句的循环次数。
1 2 3 4 5 6 7 8 9 10
a b c d e f g h i aj 
[root@centos7 temp]#

8、while list-1; do list-2; done

9、until list-1; do list-2; done

while命令会重复执行list-2,只要list-1的返回值为0;until命令会重复执行list-2,只要list-1的返回值为非0。while和until命令的返回值是最后一次执行list-2的返回值。 breakcontinue两个内置命令可以用于for、while、until循环中,分别表示跳出循环和停止本次循环开始下一次循环。

10、case word in [[(] pattern [ | pattern]...) list ;;] ... esac

case命令会将word扩展后的值和in后面的多个不同的pattern进行匹配(通配符匹配),如果匹配成功则执行相应的list。 list后使用操作符;;时,表示如果执行了本次的list,那么将不再进行下一次的匹配,case命令结束; 使用操作符;&,则表示执行完本次list后,再执行紧随其后的下一个list(不判断是否匹配); 使用操作符;;&,则表示继续下一次的匹配,如果匹配成功,那么执行相应的list。 case命令的返回值是执行最后一个命令的返回值,当匹配均没有成功时,返回值为0。

脚本举例:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#!/bin/bash
# while
unset i j
while ((i++<$(grep -c '^processor' /proc/cpuinfo)))
do
    #每个后台运行的yes命令将占满一核CPU
    yes >/dev/null &
done
# -------------------------------------------------
# until
# 获取yes进程PID数组
PIDS=($(ps -eo pid,comm|grep -oP '\d+(?= yes$)'))
# 逐个杀掉yes进程
until ! ((${#PIDS[*]}-j++))
do
    kill ${PIDS[$j-1]}
done
# -------------------------------------------------
# case
user_define_command &>/dev/null
case $? in
0) echo "执行成功" ;;
1) echo "未知错误" ;;
2) echo "误用shell命令" ;;
126) echo "权限不够" ;;
127) echo "未找到命令" ;;
130) echo "CTRL+C终止" ;;
*) echo "其他错误" ;;
esac
# -------------------------------------------------
#定义数组
c=(1 2 3 4 5)
#关于各种复合命令结合使用的例子:
echo -e "$(
for i in ${c[@]}
do
    case $i in 
    (1|2|3)
        printf "%d\n" $((i+1))
        ;;
    (4|5)
        printf "%d\n" $((i-1))
        ;;
    esac
done
)" | while read NUM
do
    if [[ $NUM -ge 4 ]];then
        printf "%s\n" "数字${NUM}大于等于4"
    else
        printf "%s\n" "数字${NUM}小于4"
    fi
done

执行结果:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
[root@centos7 temp]# ./test.sh 
./test.sh:18: 18671 已终止               yes > /dev/null
./test.sh:18: 18673 已终止               yes > /dev/null
./test.sh:18: 18675 已终止               yes > /dev/null
./test.sh:18: 18677 已终止               yes > /dev/null
./test.sh:18: 18679 已终止               yes > /dev/null
./test.sh:18: 18681 已终止               yes > /dev/null
./test.sh:20: 18683 已终止               yes > /dev/null
./test.sh:20: 18685 已终止               yes > /dev/null
未找到命令
数字2小于4
数字3小于4
数字4大于等于4
数字3小于4
数字4大于等于4
[root@centos7 temp]#

11、select name [ in word ] ; do list ; done

select命令适用于交互式菜单选择场景。word的扩展结果组成一系列可选项供用户选择,用户通过键入提示字符中可选项前的数字来选择特定项目,然后执行list,完成后继续下一轮选择,需要使用内置命令break来跳出循环。

脚本举例:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#!/bin/bash
echo "系统信息:"
select item in "host_name" "user_name" "shell_name" "quit"
do
    case $item in
     host*) hostname;;
     user*) echo $USER;;
     shell*) echo $SHELL;;
     quit) break;;
    esac
done

执行结果:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
[root@centos7 ~]# ./test.sh 
系统信息:
1) host_name
2) user_name
3) shell_name
4) quit
#? 1
centos7
#? 2
root
#? 3
/bin/bash
#? 4
[root@centos7 ~]# 

协进程命令

协进程命令是指由保留关键字coproc执行的命令(bash4.0版本以上),其命令格式为:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
coproc [NAME] command [redirections]

命令command在子shell中异步执行,就像被控制操作符&作用而放到了后台执行,同时建立起一个双向管道,连接该命令和当前shell。 执行此命令,即创建了一个协进程,如果NAME省略(command为简单命令时必须省略,此时使用默认名COPROC),则称为匿名协进程,否则称为命名协进程

此命令执行时,command的标准输出和标准输入通过双向管道分别连接到当前shell的两个文件描述符,然后文件描述符又分别赋值给了数组元素NAME[0]NAME[1]。此双向管道的建立要早于命令command的其他重定向操作。被连接的文件描述符可以当成变量来使用。子shell的pid可以通过变量NAME_PID来获得。 关于协进程的例子,我们在下一篇给出。

函数定义

bash函数定义的格式有两种:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
name () compound-command [redirection]
function name [()] compound-command [redirection]

这样定义了名为name的函数,使用保留关键字function定义函数时,括号可以省略。函数的代码块可以是任意一个上述的复合命令(compound-command)。

脚本举例:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#!/bin/bash
#常用定义方法:
func_1() {
    #局部变量
    local num=6
    #嵌套执行函数
    func_2
    #函数的return值保存在特殊变量?if [ $? -gt 10 ];then
        echo "大于10"
    else
        echo "小于等于10"
    fi
}
################
func_2()
{
    # 内置命令return使函数退出,并使其的返回值为命令后的数字
    # 如果return后没有参数,则返回函数中最后一个命令的返回值
    return $((num+5))
}
#执行。就如同执行一个简单命令。函数必须先定义后执行(包括嵌套执行的函数)
func_1
###############
#一般定义方法
#函数名后面可以是任何复合命令:
func_3() for NUM
do
    # 内置命令shift将会调整位置变量,每次执行都把前n个参数撤销,后面的参数前移。
    # 如果shift后的数字省略,则表示撤销第一个参数$1,其后参数前移($2变为$1....)
    shift
    echo -n "$((NUM+$#)) "
done
#函数内部位置变量被重置为函数的参数
func_3 `seq 10`;echo

执行结果:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
[root@centos7 temp]# ./test.sh   
大于10
10 10 10 10 10 10 10 10 10 10 
[root@centos7 temp]# 

这些就是bash的所有命令语法。bash中任何复杂难懂的语句都是这些命令的变化组合。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2017-01-11,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
Shell编程
Shell 是一个用 C 语言编写的程序,通过 Shell 用户可以访问操作系统内核服务。
用户4870038
2021/02/05
5.2K0
Shell编程
Shell脚本编程_shell简单脚本
  shell 是指一种应用程序,这个应用程序提供了一个界面,用户通过这个界面访问操作系统内核的服务,在用户和内核之间充当翻译官的角色,是一个命令解释器。Ken Thompson 的 sh 是第一种 Unix Shell,Windows Explorer 是一个典型的图形界面 shell。
全栈程序员站长
2022/11/09
8.4K0
Shell脚本编程_shell简单脚本
SHELL(bash)脚本编程四:其他扩展
在之前的文章中我们讲述了变量扩展、数学扩展和命令替换。本篇接着介绍shell中用到的其他扩展。
用户5030870
2019/04/11
8860
Linux命令(二)——shell编程
Unix/Linux上常见的Shell脚本解释器有bash、sh、csh、ksh等,习惯上把它们称作一种Shell。我们常说有多少种Shell,其实说的是Shell脚本解释器。
不愿意做鱼的小鲸鱼
2022/09/26
4K0
shell脚本编程之路3
描述:我们学过的每一种高级编程语言,都在存在流程/分支选择/循环等结构,同样shell编程中也有这是与windows上的bat编程不一样的点;shell选择分支嵌套建议不超过三层,为了执行的效率和其他人容易读懂;
全栈工程师修炼指南
2022/09/28
5540
shell脚本编程之路3
Shell编程快速入门指南
字符串可以使用单引号和双引号,单引号中不能包含单引号,即使转义单引号也不次那个,双引号则可以,双引号也可以使用字符串。
用户1515472
2019/07/24
7870
Bash 手册 v3.2 - 3
3.2 Shell命令 =============     一个简单命令如echo a b c由命令自身和后面的变元组成, 并以空格分隔.     复杂命令是由简单命令用以下方式组合而成: 管道线(使前面命令的输出变成后面 命令的输入), 循环或条件结构, 或者其他组合形式. 3.2.1 简单命令 --------------     简单命令是最常见的命令. 一个简单命令就是一串以控制操作符结尾并用空白符 (*参见 2 定义::)分隔的单词. 通常第一个单词指定了要执行的命令, 剩余的单词 都是该命令的变元.     一个简单命令的返回状态就是POSIX 1003.1 waitpid函数提供的退出状态. 如果 命令被信号n终结, 则其返回状态是128+n. 3.2.2 管道线 ------------     一个管道线就是由'|'分隔的一串简单命令.     管道线的形式是:         [time [-p]] [!] command1 [| command2 ... ] 管道线中每个命令的输出通过管道连接到下一个命令的输入, 就是说, 每个命令读取 了前一个命令的输出.     使用保留字time会在管道线执行结束时打印出其计时数据. 目前计时数据包含该 管道线执行所消耗的总逝去时间, 用户态时间和系统态时间. 选项'-p'把时间输出 格式调整为POSIX所指定的格式. 可以设置TIMEFORMAT变量来指定如何显示时间信息. 关于有哪些可用的格式, *参见 5.2 Bash变量. 将time作为保留字使用使得对shell 内部命令, shell函数, 及管道线的时间测量成为可能. 这一点如果用外部time命令 则不容易做到.     如果管道线不是异步地执行(*参见 3.2.3 命令列表::), 则shell会等待管道线 中所有命令运行结束.     管道线中的每个命令都在各自的子shell中运行(*参见 3.7.3 命令执行环境). 如果pipefail选项被关闭(*参见 4.3 Set内部命令), 管道线的退出状态就是管道线 中最后一个结束命令的退出状态. 如果pipefail选项开启, 管道线的退出状态是最后 (最右)一个拥有非零退出状态的命令的退出状态, 或是0如果所有命令都成功退出. 若 管道线前面出现保留字'!', 则退出状态是上述所描述情况的逻辑反. Shell等到管道 线内所有命令结束才返回值. 3.2.3 命令列表 --------------     列表是指一个或多个管道线组成的序列, 它们以';', '&', '&&' 或'||'分隔, 并可选地以';', '&', 或newline结束.     在这些列表操作符中, '&&'和'||'具有相同的优先级, ';'和'&'具有相同的优先 级, 且'&&'和'||'的优先级比';'和'&'要高.     在列表中, 也可用一个或多个newline组成的序列来分隔命令, 这点上和';'等价.     当一个命令以控制操作符'&'结尾时, shell将该命令放入一个子shell中异步地 执行. 这也被称为将命令放在后台执行. Shell不会等该命令结束, 而是立即以返回 状态0(真)返回. 在shell的任务控制功能没有启用(*参见 7 任务控制), 而且又没有 任何显式的重定向的时候, 此异步命令的输入将会从/dev/null重定向而得.     用';'分隔的命令顺序地执行; shell依次等待每个命令执行完毕. 最后的返回 状态由最后一个命令的退出状态决定.     控制操作符'&&'和'||'分别表示列表的'与'和'或'. 列表与的形式是:         command1 && command2 当且仅当command1的退出状态为零时command2才被执行.     列表或的形式为:         command1 || command2 当且仅当command1的退出状态非零时command2才被执行.     列表与和列表或的返回状态由列表中最后一个执行的命令的退出状态决定. 3.2.4 复合命令 --------------     符号命令是shell编程特性的一个构造. 每个构造以一个保留字或控制操作符开始, 以一个对应的保留字或控制操作符结束. 在没有显式覆盖时, 任何针对复合命令的重 定向都对该复合命令内的所有命令起作用.     Bash提供循环结构, 条件结构, 以及将命令组合起来作为一个基本单元的机制. 3.2.4.1 循环结构 ................     Bash支持以下循环结构.     注意在以下命令语法描述中, 任何';'出现的地方都可以用一个或多个newline替代. 'until
py3study
2020/01/14
1.7K0
高级shell脚本编程指南_python的快速入门
什么是shell呢?shell是用C语言编写的程序,它是用户使用 Linux 的桥梁。Shell既是一种命令语言,又是一种程序设计语言。简单来说Shell 是指一种应用程序,这个应用程序提供了一个界面,用户通过这个界面访问操作系统内核的服务。也可以这样认为,linux中的shell就是linux内核的一个外层保护工具,并负责完成用户与内核之间的交互
全栈程序员站长
2022/11/09
3.3K0
高级shell脚本编程指南_python的快速入门
一文掌握shell脚本的基本语法
欢迎大家star我的GitHub:https://github.com/SolerHo/geeks-shell,建议直接使用GitHub来查看排版,发现markdown有错位的情况。
阳光罗诺
2022/01/03
4.6K0
一文掌握shell脚本的基本语法
Shell
vim调试,/{匹配字符}可以查找相应的位置,N往后查找下一个,shift+N往前。
matt
2022/10/25
1.4K0
Shell编程基础
请参考:菜鸟教程参数传递 在执行脚本的时候可以向脚本传递参数,脚本获取参数的格式为:$n
lin_zone
2018/08/15
8730
SHELL(bash)脚本编程三:重定向
在这一篇中,我们介绍了一点关于输入输出重定向和管道的基础知识,本篇将继续重定向的话题。 在开始前,先说一说shell中的引用。
用户5030870
2019/04/11
1.9K0
Shell入门知识
李家酒馆酒保
2017/12/28
9420
Shell入门知识
每天学一个 Linux 命令(95):test
test 命令执行条件表达式,用于检查文件类型并比较值,评估条件。如果为 true,则返回 0 退出状态,否则返回 1。
民工哥
2021/04/21
8910
Linux从入门到精通(十二)——shell编程
Shell脚本:按照一定的语法结构把若干linux命令组合在一起,实现特定的功能。
传说之下的花儿
2023/04/16
5.1K0
Shell 编程语法基础
在Shell脚本中,定义变量直接赋值即可,使用变量时需要在变量名前加美元符号$,注意定义变量时变量名和等号之间不能有空格。 变量名的命名必须遵循以下规则:
嵌入式视觉
2022/09/05
2.4K0
Shell 编程语法基础
shell脚本编程之路2
描述:主要是数值命令如declare/let/expr、数值运算方法、变量测试,以及shell变量的弱点默认字符串类型(弱类型)
全栈工程师修炼指南
2022/09/28
1.4K0
shell脚本编程之路2
02 . Shell变量和逻辑判断及循环使用
while循环用于不断执行一系列命令,也用于从输入文件中读取数据;命令通常为测试条件。其格式为:
iginkgo18
2020/09/27
1.6K0
Shell脚本学习2
Bash 支持很多运算符,包括算数运算符、关系运算符、布尔运算符、字符串运算符和文件测试运算符。
用户9645905
2023/10/17
3000
Shell 基础语法
本文只是对 shell 脚本语言中一些常用的基础语法进行汇总整理,如果你真的想系统的学习 shell 脚本编程,这里推荐两本电子读物:
Ryoma
2022/04/02
1.1K0
Shell 基础语法
相关推荐
Shell编程
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档