Shell——基础(一)

什么是 shell?

真正能够控制计算机硬件(CPU、内存、显示器等)的只有操作系统内核(Kernel)。

由于安全、复杂、繁琐等原因,用户不能直接接触内核(也没有必要),需要另外再开发一个程序,让用户直接使用这个程序;该程序的作用就是接收用户的操作(点击图标、输入命令),并进行简单的处理,然后再传递给内核,这样用户就能间接地使用操作系统内核了。

shell就是linux 命令与 linux 内核间的代理; 对一个纯文本的文件进行解析,然后执行这些功能,也可以说 Shell 脚本就是一系列命令的集合。

语法规范

1
2
!/bin/bash  
echo "Hello World"
1
2
3
cd 到该目录下  
chmod +x ./test.sh 给脚本权限
./test.sh 执行脚本

也可以直接 sh test.sh,无须!/bin/bash

变量

shell 中,每一个变量的值都是字符串,无论你给变量赋值时有没有使用引号,值都会以字符串的形式存储。

定义变量

Shell 支持以下三种定义变量的方式:

1
2
3
variable=value 
variable='value'
variable="value"

Shell 变量的命名规范和大部分编程语言都一样:

  • 变量名由数字、字母、下划线组成;
  • 必须以字母或者下划线开头;
  • 不能使用 Shell 里的关键字(通过 help 命令可以查看保留关键字)。

单引号与双引号

  • variable 是变量名,value 是赋给变量的值。如果 value 不包含任何空白符(例如空格、Tab 缩进等),那么可以不使用引号;如果 value 包含了空白符,那么就必须使用引号包围起来。
  • 以单引号’ ‘包围变量的值时,单引号里面是什么就输出什么,即使内容中有变量和命令(命令需要反引起来)也会把它们原样输出。
  • 以双引号” “包围变量的值时,输出时会先解析里面的变量和命令,而不是把双引号中的变量名和命令原样输出。

如果变量的内容是数字,那么可以不加引号;如果真的需要原样输出就加单引号;其他没有特别要求的字符串等最好都加上双引号,定义变量时加双引号是最常见的使用场景。

访问变量

1
2
3
myText="hello world"  
echo $myText
echo ${myText}

变量名外面的花括号{v}是可选的,加不加都行,加花括号是为了帮助解释器识别变量的边界。

只读变量

使用 readonly 命令可以将变量定义为只读变量,只读变量的值不能被改变。

下面的例子尝试更改只读变量,结果报错:

1
2
3
4
!/bin/bash
myUrl="http://c.biancheng.net/shell/"
readonly myUrl
myUrl="http://c.biancheng.net/shell/"

删除变量

1
unset variable_name

变量被删除后不能再次使用;unset 命令不能删除只读变量。

将命令的结果赋予变量

第一种方式把命令用反引号(位于 Esc 键的下方)包围起来,反引号和单引号非常相似,容易产生混淆,所以不推荐使用这种方式;

第二种方式把命令用$()包围起来,区分更加明显,所以推荐使用这种方式。

command 可以只有一个命令,也可以有多个命令,多个命令之间以分号;分隔。

1
2
3
4
variable=`command`
variable1=$(command)
echo $variable
echo $variable1

如果被替换的命令的输出内容包括多行(也即有换行符),或者含有多个连续的空白符,那么在输出变量时应该将变量用双引号包围,否则系统会使用默认的空白符来填充,这会导致换行无效,以及连续的空白符被压缩成一个。

1
2
3
4
5
!/bin/bash
LSL=`ls -l`
echo $LSL 不使用双引号包围
echo "--------------------------" 输出分隔符
echo "$LSL" 使用引号包围

要注意的是,$() 仅在 Bash Shell 中有效,而反引号可在多种 Shell 中使用。所以这两种命令替换的方式各有特点,究竟选用哪种方式全看个人需求。

位置参数

运行 Shell 脚本文件时我们可以给它传递一些参数,这些参数在脚本文件内部可以使用$n的形式来接收,例如,$1 表示第一个参数,$2 表示第二个参数,依次类推。

  1. 给脚本文件传递位置参数

    1
    2
    3
    !/bin/bash
    echo "Language: $1"
    echo "URL: $2"

    运行,并附带参数:

    1
    2
    3
    4
    [mozhiyan@localhost ~]$ cd demo   
    [mozhiyan@localhost demo]$ . ./test.sh Shell http://c.biancheng.net/shell/
    Language: Shell
    URL: http://c.biancheng.net/shell/

    其中Shell是第一个位置参数,http://c.biancheng.net/shell 是第二个位置参数,两者之间以空格分隔。

  2. 给函数传递位置参数

    1
    2
    3
    4
    5
    6
    7
    8
    !/bin/bash
    定义函数
    function func(){
    echo "Language: $1"
    echo "URL: $2"
    }
    调用函数
    func C++ http://c.biancheng.net/cplus/

    运行:

    1
    2
    [mozhiyan@localhost ~]$ cd demo
    [mozhiyan@localhost demo]$ . ./test.sh Language: C++ URL: http://c.biancheng.net/cplus/

如果参数个数太多,达到或者超过了 10 个,那么就得用${n}的形式来接收了,例如 ${10}、${23}。{ }的作用是为了帮助解释器识别参数的边界,这跟使用变量时加{ }是一样的效果。

特殊变量

1
2
3
4
5
6
7
$0	当前脚本的文件名。
$n(n≥1) 传递给脚本或函数的参数。n 是一个数字,表示第几个参数。例如,第一个参数是 $1,第二个参数是 $2。
$ 传递给脚本或函数的参数个数。
$* 传递给脚本或函数的所有参数。
$@ 传递给脚本或函数的所有参数。当被双引号" "包含时,$@ 与 $* 稍有不同,我们将在《Shell $*和$@的区别》一节中详细讲解。
$? 上个命令的退出状态,或函数的返回值,我们将在《Shell $?》一节中详细讲解。
$$ 当前 Shell 进程 ID。对于 Shell 脚本,就是这些脚本所在的进程 ID。

可以不遵守一般变量的命名规范。

字符串变量

  1. 获取字符串长度:

    ${string_name}

  2. 字符串拼接:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    !/bin/bash
    name="Shell"
    url="http://c.biancheng.net/shell/"
    str1=$name$url 中间不能有空格
    str2="$name $url" 如果被双引号包围,那么中间可以有空格
    str3=$name": "$url 中间可以出现别的字符串
    str4="$name: $url" 这样写也可以
    str5="${name}Script: ${url}index.html" 这个时候需要给变量名加上大括号
    echo $str1
    echo $str2
    echo $str3
    echo $str4
    echo $str5
  3. 字符串截取

    1
    2
    3
    4
    5
    6
    7
    8
    ${string: start :length}	从 string 字符串的左边第 start 个字符开始,向右截取 length 个字符。
    ${string: start} 从 string 字符串的左边第 start 个字符开始截取,直到最后。
    ${string: 0-start :length} 从 string 字符串的右边第 start 个字符开始,向右截取 length 个字符。
    ${string: 0-start} 从 string 字符串的右边第 start 个字符开始截取,直到最后。
    ${string*chars} 从 string 字符串第一次出现 *chars 的位置开始,截取 *chars 右边的所有字符。
    ${string*chars} 从 string 字符串最后一次出现 *chars 的位置开始,截取 *chars 右边的所有字符。
    ${string%*chars} 从 string 字符串第一次出现 *chars 的位置开始,截取 *chars 左边的所有字符。
    ${string%%*chars} 从 string 字符串最后一次出现 *chars 的位置开始,截取 *chars 左边的所有字符。

数组

Shell 并且没有限制数组的大小,理论上可以存放无限量的数据。Shell 是弱类型的,它并不要求所有数组元素的类型必须相同

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
nums=(29 100 13 8 91 44) 以()表示,元素之间须空格
arr=(20 56 "http://c.biancheng.net/shell/") 元素无须统一
nums[6]=88 赋值
ages=([3]=24 [5]=19 [10]=12) 一起赋值

echo ${nums[3]} 获取数组第二个元素
${nums[*]} */@ 都可以获取所有元素
${nums[@]}

${array_name[@]} 获取数组长度
${array_name[*]}
${arr[2]} 获取元素长度

array_new=(${array1[@]} ${array2[@]}) 数组拼接
array_new=(${array1[*]} ${array2[*]})

unset arr[1] 删除指定数组元素
unset arr 删除数组

内建命令

所谓 Shell 内建命令,就是由 Bash 自身提供的命令,而不是文件系统中的某个可执行文件。

内建命令会比外部命令执行得更快,执行外部命令时不但会触发磁盘 I/O,还需要 fork 出一个单独的进程来执行,执行完成后再退出。而执行内建命令相当于调用当前 Shell 进程的一个函数。

alias命令

alisa 用来给命令创建一个别名。

1
2
3
4
5
6
7
!/bin/bash
alias timestamp='date +%s'
begin=`timestamp`
sleep 20s
finish=$(timestamp)
difference=$((finish - begin))
echo "run time: ${difference}s"

unalias用来删除当前进程别名。

echo命令

用来在终端输出字符串,并在最后默认加上换行符。

echo 命令输出结束后默认会换行,如果不希望换行,可以加上-n参数,如下所示:

1
2
3
4
5
6
7
8
9
!/bin/bash
name="Tom"
age=20
height=175
weight=62
echo -n "${name} is ${age} years old, "
echo -n "${height}cm in height "
echo "and ${weight}kg in weight."
echo "Thank you!

默认情况下,echo 不会解析以反斜杠\开头的转义字符。我们可以添加-e参数来让 echo 命令解析转义字符。例如:

1
2
3
[root@localhost ~] echo -e "hello \nworld"
hello
world

有了-e参数,我们也可以使用转义字符\c来强制 echo 命令不换行。

read命令

read 是 Shell 内置命令,用来从标准输入中读取数据并赋值给变量。如果没有进行重定向,默认就是从键盘读取用户输入的数据;如果进行了重定向,那么可以从文件中读取数据。

使用 read 命令给多个变量赋值:

1
2
3
4
5
!/bin/bash
read -p "Enter some information > " name url age
echo "网站名字:$name"
echo "网址:$url"
echo "年龄:$age"

只读取一个字符:

1
2
3
4
!/bin/bash
read -n 1 -p "Enter a char > " char
printf "\n" 换行
echo $char

在指定时间内输入密码:

1
2
3
4
5
6
7
8
9
10
!/bin/bash
if
read -t 20 -sp "Enter password in 20 seconds(once) > " pass1 && printf "\n" && 第一次输入密码
read -t 20 -sp "Enter password in 20 seconds(again)> " pass2 && printf "\n" && 第二次输入密码
[ $pass1 == $pass2 ] 判断两次输入的密码是否相等
then
echo "Valid password"
else
echo "Invalid password"
fi

exit命令

exit 是一个 Shell 内置命令,用来退出当前 Shell 进程,并返回一个退出状态;

exit 命令可以接受一个整数值作为参数,代表退出状态。如果不指定,默认状态值是 0。

一般情况下,退出状态为 0 表示成功,退出状态为非 0 表示执行失败(出错)了。

使用$?来获取退出状态。

declare命令

declare 和 typeset 都是 Shell 内建命令,它们的用法相同,都用来设置变量的属性。不过 typeset 已经被弃用了,建议使用 declare 代替。

declare [+/-] [aAfFgilprtux] [变量名=变量值]

1
2
3
4
5
6
7
8
9
-f [name]	列出之前由用户在脚本中定义的函数名称和函数体。
-F [name] 仅列出自定义函数名称。
-g name 在 Shell 函数内部创建全局变量。
-p [name] 显示指定变量的属性和值。
-a name 声明变量为普通数组。
-A name 声明变量为关联数组(支持索引下标为字符串)。
-i name 将变量定义为整数型。
-r name[=value] 将变量定义为只读(不可修改和删除),等价于 readonly name。
-x name[=value] 将变量设置为环境变量,等价于 export name[=value]。

将变量声明为整数并进行计算:

1
2
3
4
5
6
!/bin/bash
declare -i m n ret 将多个变量声明为整数
m=10
n=30
ret=$m+$n
echo $ret

运行结果:
40

将变量定义为只读变量:

1
2
3
4
5
[c.biancheng.net]$ declare -r n=10
[c.biancheng.net]$ n=20
bash: n: 只读变量
[c.biancheng.net]$ echo $n
10

显示变量的属性和值:

1
2
3
[c.biancheng.net]$ declare -r n=10
[c.biancheng.net]$ declare -p n
declare -r n="10"

运算

通俗地讲,就是将数学运算表达式放在((和))之间。

表达式可以只有一个,也可以有多个,多个表达式之间以逗号,分隔。对于多个表达式的情况,以最后一个表达式的值作为整个 (( )) 命令的执行结果。

可以使用$获取 (( )) 命令的结果,这和使用$获得变量值是类似的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
[c.biancheng.net]$ ((a=1+2**3-4%3))
[c.biancheng.net]$ echo $a
8
[c.biancheng.net]$ b=$((1+2**3-4%3)) 运算后将结果赋值给变量,变量放在了括号的外面。
[c.biancheng.net]$ echo $b
8
[c.biancheng.net]$ echo $((1+2**3-4%3)) 也可以直接将表达式的结果输出,注意不要丢掉 $ 符号。
8
[c.biancheng.net]$ a=$((100*(100+1)/2)) 利用公式计算1+2+3+...+100的和。
[c.biancheng.net]$ echo $a
5050
[c.biancheng.net]$ echo $((100*(100+1)/2)) 也可以直接输出表达式的结果。
5050
[c.biancheng.net]$ echo $((3<8)) 3<8 的结果是成立的,因此,输出了 1,1 表示真
1
[c.biancheng.net]$ echo $((8<3)) 8<3 的结果是不成立的,因此,输出了 0,0 表示假。
0
[c.biancheng.net]$ echo $((8==8)) 判断是否相等。
1
[c.biancheng.net]$ ((a=3+5, b=a+10)) 先计算第一个表达式,再计算第二个表达式
[c.biancheng.net]$ echo $a $b
8 18
[c.biancheng.net]$ c=$((4+8, a+b)) 以最后一个表达式的结果作为整个(())命令的执行结果
[c.biancheng.net]$ echo $c
26

表达式

if else

1
2
3
4
5
6
7
8
9
10
11
12
13
if  condition1
then
statement1
elif condition2
then
statement2
elif condition3
then
statement3
……
else
statementn
fi

如果 condition 成立,那么 then 后边的 statement1 语句将会被执行;否则,执行 else 后边的 statement2 语句。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
!/bin/bash
read age
if (( $age <= 2 )); then
echo "婴儿"
elif (( $age >= 3 && $age <= 8 )); then
echo "幼儿"
elif (( $age >= 9 && $age <= 17 )); then
echo "少年"
elif (( $age >= 18 && $age <=25 )); then
echo "成年"
elif (( $age >= 26 && $age <= 40 )); then
echo "青年"
elif (( $age >= 41 && $age <= 60 )); then
echo "中年"
else
echo "老年"
fi

test命令

test 是 Shell 内置命令,用来检测某个条件是否成立。test 通常和 if 语句一起使用,并且大部分 if 语句都依赖 test。

test 命令也可以简写为[],它的用法为:

[ expression ]

注意[]和expression之间的空格,这两个空格是必须的,否则会导致语法错误。[]的写法更加简洁,比 test 使用频率高。

  1. 与数值比较相关的 test 选​项

    1
    2
    3
    4
    5
    6
    num1 -eq num2	判断 num1 是否和 num2 相等。
    num1 -ne num2 判断 num1 是否和 num2 不相等。
    num1 -gt num2 判断 num1 是否大于 num2 。
    num1 -lt num2 判断 num1 是否小于 num2。
    num1 -ge num2 判断 num1 是否大于等于 num2。
    num1 -le num2 判断 num1 是否小于等于 num2。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    !/bin/bash
    read age
    if test $age -le 2; then
    echo "婴儿"
    elif test $age -ge 3 && test $age -le 8; then
    echo "幼儿"
    elif [ $age -ge 9 ] && [ $age -le 17 ]; then
    echo "少年"
    elif [ $age -ge 18 ] && [ $age -le 25 ]; then
    echo "成年"
    elif test $age -ge 26 && test $age -le 40; then
    echo "青年"
    elif test $age -ge 41 && [ $age -le 60 ]; then
    echo "中年"
    else
    echo "老年"
    fi
  2. 与文件检测相关的 test 选项:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    -b filename	判断文件是否存在,并且是否为块设备文件。
    -c filename 判断文件是否存在,并且是否为字符设备文件。
    -d filename 判断文件是否存在,并且是否为目录文件。
    -e filename 判断文件是否存在。
    -f filename 判断文件是否存在,井且是否为普通文件。
    -L filename 判断文件是否存在,并且是否为符号链接文件。
    -p filename 判断文件是否存在,并且是否为管道文件。
    -s filename 判断文件是否存在,并且是否为非空。
    -S filename 判断该文件是否存在,并且是否为套接字文件。
    -r filename 判断文件是否存在,并且是否拥有读权限。
    -w filename 判断文件是否存在,并且是否拥有写权限。
    -x filename 判断文件是否存在,并且是否拥有执行权限。
    -u filename 判断文件是否存在,并且是否拥有 SUID 权限。
    -g filename 判断文件是否存在,并且是否拥有 SGID 权限。
    -k filename 判断该文件是否存在,并且是否拥有 SBIT 权限。
    filename1 -nt filename2 判断 filename1 的修改时间是否比 filename2 的新。
    filename -ot filename2 判断 filename1 的修改时间是否比 filename2 的旧。
    filename1 -ef filename2 判断 filename1 是否和 filename2 的 inode 号一致,可以理解为两个文件是否为同一个文件。这个判断用于判断硬链接是很好的方法
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    !/bin/bash
    read filename
    read url
    if test -w $filename && test -n $url
    then
    echo $url > $filename
    echo "写入成功"
    else
    echo "写入失败"
    fi
  3. 与字符串判断相关的 test 选项

    1
    2
    3
    4
    5
    6
    7
    -z str	判断字符串 str 是否为空。
    -n str 判断宇符串 str 是否为非空。
    str1 = str2
    str1 == str2 =和==是等价的,都用来判断 str1 是否和 str2 相等。
    str1 != str2 判断 str1 是否和 str2 不相等。
    str1 \> str2 判断 str1 是否大于 str2。\>是>的转义字符,这样写是为了防止>被误认为成重定向运算符。
    str1 \< str2 判断 str1 是否小于 str2。同样,\<也是转义字符。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    !/bin/bash
    read str1
    read str2
    检测字符串是否为空
    if [ -z "$str1" ] || [ -z "$str2" ]
    then
    echo "字符串不能为空"
    exit 0
    fi
    比较字符串
    if [ $str1 = $str2 ]
    then
    echo "两个字符串相等"
    else
    echo "两个字符串不相等"
    fi
  4. 与逻辑运算相关的 test 选项

    1
    2
    3
    expression1 -a expression	逻辑与,表达式 expression1 和 expression2 都成立,最终的结果才是成立的。
    expression1 -o expression2 逻辑或,表达式 expression1 和 expression2 有一个成立,最终的结果就成立。
    !expression 逻辑非,对 expression 进行取反。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    !/bin/bash
    read str1
    read str2
    检测字符串是否为空
    if [ -z "$str1" -o -z "$str2" ] 使用 -o 选项取代之前的 ||
    then
    echo "字符串不能为空"
    exit 0
    fi
    比较字符串
    if [ $str1 = $str2 ]
    then
    echo "两个字符串相等"
    else
    echo "两个字符串不相等"
    fi

[[]] 命令

test的升级版,[[ ]] 是 Shell 内置关键字,不是命令,在使用时没有给函数传递参数的过程,所以 test 命令的某些注意事项在 [[ ]] 中就不存在了,具体包括:

  • 不需要把变量名用双引号””包围起来,即使变量是空值,也不会出错。
  • 不需要、也不能对 >、< 进行转义,转义后会出错。

注意,[[ ]] 剔除了 test 命令的-o和-a选项,你只能使用 || 和 &&。

在 Shell [[ ]] 中,可以使用=~来检测字符串是否符合某个正则表达式,它的用法为:

[[ str =~ regex ]]

1
2
3
4
5
6
7
8
!/bin/bash
read tel
if [[ $tel =~ ^1[0-9]{10}$ ]]
then
echo "你输入的是手机号码"
else
echo "你输入的不是手机号码"
fi

有了 [[ ]],你还有什么理由使用 test 或者 [ ],[[ ]] 完全可以替代之,而且更加方便,更加强大。

case in

当分支较多,并且判断条件比较简单时,使用 case in 语句就比较方便了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
case expression in
pattern1)
statement1
;;
pattern2)
statement2
;;
pattern3)
statement3
;;
……
*)
statementn
esac
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
printf "Input integer number: "
read num
case $num in
1)
echo "Monday"
;;
2)
echo "Tuesday"
;;
3)
echo "Wednesday"
;;
4)
echo "Thursday"
;;
5)
echo "Friday"
;;
6)
echo "Saturday"
;;
7)
echo "Sunday"
;;
*)
echo "error"
esac

case in 的 pattern 部分支持简单的正则表达式,具体来说,可以使用以下几种格式:

1
2
3
4
*	表示任意字符串。
[abc] 表示 a、b、c 三个字符中的任意一个。比如,[15ZH] 表示 1、5、Z、H 四个字符中的任意一个。
[m-n] 表示从 m 到 n 的任意一个字符。比如,[0-9] 表示任意一个数字,[0-9a-zA-Z] 表示字母或数字。
| 表示多重选择,类似逻辑运算中的或运算。比如,abc | xyz 表示匹配字符串 "abc" 或者 "xyz"。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
!/bin/bash
printf "Input a character: "
read -n 1 char
case $char in
[a-zA-Z])
printf "\nletter\n"
;;
[0-9])
printf "\nDigit\n"
;;
[0-9])
printf "\nDigit\n"
;;
[,.?!])
printf "\nPunctuation\n"
;;
*)
printf "\nerror\n"
esac

while

while 循环是 Shell 脚本中最简单的一种循环,当条件满足时,while 重复地执行一组语句,当条件不满足时,就退出 while 循环。

1
2
3
4
while condition
do
statements
done
1
2
3
4
5
6
7
8
9
!/bin/bash
i=1
sum=0
while ((i <= 100))
do
((sum += i))
((i++))
done
echo "The sum is: $sum"

util

unti 循环和 while 循环恰好相反,当判断条件不成立时才进行循环,一旦判断条件成立,就终止循环。

1
2
3
4
until condition
do
statements
done
1
2
3
4
5
6
7
8
9
!/bin/bash
i=1
sum=0
until ((i > 100))
do
((sum += i))
((i++))
done
echo "The sum is: $sum"

util循环使用较少,一般使用while即可。

for

  1. C语言风格的 for 循环的用法如下:

    1
    2
    3
    4
    for((exp1; exp2; exp3))
    do
    statements
    done
    1
    2
    3
    4
    5
    6
    7
    !/bin/bash
    sum=0
    for ((i=1; i<=100; i++))
    do
    ((sum += i))
    done
    echo "The sum is: $sum"
  2. Python 风格的 for in 循环

    1
    2
    3
    4
    for variable in value_list
    do
    statements
    done

    valuelist的写法:

    1
    2
    3
    4
    5
    6
    7
    8
    !/bin/bash
    sum=0
    for n in 1 2 3 4 5 6
    do
    echo $n
    ((sum+=n))
    done
    echo "The sum is "$sum

    1到100的和:

    1
    2
    3
    4
    5
    6
    7
    !/bin/bash
    sum=0
    for n in {1..100}
    do
    ((sum+=n))
    done
    echo $sum

    打印A-z:

    1
    2
    3
    4
    5
    !/bin/bash
    for c in {A..z}
    do
    printf "%c" $c
    done

    打印当前目录所有.sh文件:

    1
    2
    3
    4
    5
    !/bin/bash
    for filename in $(ls *.sh)
    do
    echo $filename
    done

函数

Shell 函数的本质是一段可以重复使用的脚本代码,这段代码被提前编写好了,放在了指定的位置,使用时直接调取即可。

定义函数

Shell 函数定义的语法格式如下:

1
2
3
4
5
Shell 函数定义的语法格式如下:
function name() {
statements
[return value]
}

如果你嫌麻烦,函数定义时也可以不写 function 关键字,如果写了 function 关键字,也可以省略函数名后面的小括号。

函数调用

调用 Shell 函数时可以给它传递参数,也可以不传递。如果不传递参数,直接给出函数名字即可:

name

如果传递参数,那么多个参数之间以空格分隔:

name param1 param2 param3

1
2
3
4
5
6
7
!/bin/bash
函数定义
function url(){
echo "http://c.biancheng.net/shell/"
}
函数调用
url

你可以将调用放在定义的前面,没有影响。

文章目录
  1. 1. 什么是 shell?
  2. 2. 语法规范
  3. 3. 变量
    1. 3.1. 定义变量
    2. 3.2. 单引号与双引号
    3. 3.3. 访问变量
    4. 3.4. 只读变量
    5. 3.5. 删除变量
    6. 3.6. 将命令的结果赋予变量
    7. 3.7. 位置参数
    8. 3.8. 特殊变量
  4. 4. 数组
  5. 5. 内建命令
  6. 6. 运算
    1. 6.1. 表达式
    2. 6.2. test命令
    3. 6.3. [[]] 命令
    4. 6.4. case in
    5. 6.5. while
    6. 6.6. for
  7. 7. 函数
    1. 7.1. 定义函数
    2. 7.2. 函数调用
|