Shell 本身并不是内核的一部分,它只是站在内核的基础上编写的一个应用程序,是用户和Linux文件系统之间的桥梁。Shell 有自己的特殊性,就是开机立马启动,并呈现在用户面前;用户通过 Shell 来使用 Linux,不启动 Shell 的话,用户就没办法使用Linux。
Shell是一种解释性的命令行界面(CLI),它为用户提供了与操作系统内核进行交互的方式。在Linux和UNIX系统中,Shell是一种基本的用户界面工具,用于执行命令、管理文件系统、启动程序等。
常见的Shell有Bourne Shell(sh)、Bash(Bourne Again SHell)、C Shell(csh)和Korn Shell(ksh)等。其中,Bash是最常用的Shell,也是许多Linux发行版的默认Shell。
以下是Shell的一些主要特点和功能:
Shell是Linux系统中强大且灵活的工具,它为用户提供了直接与操作系统交互的方式,可以根据用户需求执行各种任务和操作。通过学习和熟悉Shell,用户可以更好地管理和控制他们的系统。
Shell 是提供与内核沟通接口的命令解释器程序,但实际上 Shell 是这种解释器的统称,Linux 系统的 Shell 种类很多,包括 Bourne Shell(简称 sh)、Bourne Again Shell(简称 bash)、C Shell(简称 csh)、K shell(简称 ksh)等等。如下图:
也就是说 sh 和 bash 都是 Linux 系统 Shell 的一种,其中 bash 命令是 sh 命令的超集,大多数 sh 脚本都可以在 bash 下运行。Linux 系统中预设默认使用的就是 bash。
She Bang是Shell脚本的第一行:#!/bin/bash
,通常是用来指定要运行的脚本的解释器。
#!
就是告诉系统解释此脚本文件的 Shell 程序在哪(其后路径所指定的程序)/bin/bash
是解释器的路径。所以 She Bang的格式重要,格式不正确会导致命令工作不正常。其中大家要记住的是:
sh
和bash
source
和.
.
代表带路径运行 在计算机编程中,脚本是用于适当的运行时环境的一组命令,这些命令用于自动执行任务。
我们经常说的 Shell 脚本,其实就是利用 Shell 的功能,编写能够直接运行的脚本文件。
: '
这就是注释
'
<< EOF
用分界符注释
不是EOF也可以,但是EOF是规范
EOF
在Shell中,变量是用来存储数据的一种方式。它们可以是数字、字符串或任何其他类型的数据。
Shell中的变量名是以美元符号($)开头的字符串,其后跟着变量名。不能在变量名中使用空格或标点符号(除了下划线),也不能以数字开头。变量名区分大小写。
下面是一些常见的Shell变量:
Shell中使用等号(=)来给变量赋值,例如:
MY_VAR="Hello, world!"
在Shell中,可以使用echo命令来显示变量的值,例如:
echo $MY_VAR
输出结果为:
Hello, world!
可以使用unset命令来删除一个变量,例如:
unset MY_VAR
以上就是Shell中的变量的基本知识。掌握了变量的使用方法,可以更加灵活地编写Shell脚本。
在Shell中,引号用于将字符串括起来。引号可以是单引号、双引号或反引号。
echo 'Hello $USER'
输出结果为:
Hello $USER
echo "Hello $USER"
输出结果为:
Hello username
echo "The date is `date`"
输出结果为:
The date is Wed Nov 24 04:27:38 UTC 2021
需要注意的是,在使用双引号时,如果想要将某些特殊字符视为普通字符而不进行转义,可以使用反斜杠(\)对其进行转义。例如:
echo "Hello \$USER"
输出结果为:
Hello $USER
在一些情况下,引号的使用可以影响变量的展开和命令的执行结果。因此,在编写Shell脚本时,需要根据具体情况来选择合适的引号。
Shell中的位置参数指的是命令行上给定的参数,它们按照出现的顺序被依次编号为$1、$2等。其中,$0表示命令本身的名称。
例如,假设有一个名为test.sh的脚本,可以这样在命令行上给其传递参数:
./test.sh arg1 arg2 arg3
在test.sh脚本中,可以使用位置参数来获取这些参数值:
echo "第一个参数为:$1"
echo "第二个参数为:$2"
echo "第三个参数为:$3"
输出结果为:
第一个参数为:arg1
第二个参数为:arg2
第三个参数为:arg3
如果需要获取所有的位置参数,可以使用 @ 或 @或 @或*来表示。这两个变量都表示所有的位置参数,不同之处在于如果将它们放在引号内, ∗ 会将所有参数解释成一个字符串,而 *会将所有参数解释成一个字符串,而 ∗会将所有参数解释成一个字符串,而@则会将每个参数解释成一个独立的字符串。
例如:
#!/bin/bash
echo "所有的参数为:$*"
echo "所有的参数为:$@"
执行命令:
./test.sh arg1 arg2 arg3
输出结果为:
所有的参数为:arg1 arg2 arg3
所有的参数为:arg1 arg2 arg3
需要注意的是,如果参数中包含空格等特殊字符,需要用引号将其括起来以避免解释错误。例如:
./test.sh "arg1 with space" arg2 "arg3 with space"
在脚本中使用位置参数时,也可以通过shift命令将参数左移一位,以便获取下一个参数。例如:
#!/bin/bash
echo "第一个参数为:$1"
shift
echo "第二个参数为:$1"
执行命令:
./test.sh arg1 arg2 arg3
输出结果为:
第一个参数为:arg1
第二个参数为:arg2
这就是Shell中的位置参数。通过它们,可以让Shell脚本处理多个参数,并根据具体需求对其进行处理。
Shell中有一些特殊变量,它们具有特定的含义和功能。以下是一些常见的Shell特殊变量:
$0
这个变量保存了当前脚本或命令的名称。例如,在一个名为myscript.sh
的Shell脚本中,$0
将会是myscript.sh
。
#!/bin/bash
echo "The name of this script is: $0"
执行上述脚本,输出结果为:
The name of this script is: myscript.sh
$1
, $2
, …这些变量用来表示位置参数,即命令行上给定的参数。例如,在执行脚本时,可以使用$1
来获取第一个参数,使用$2
来获取第二个参数,以此类推。
#!/bin/bash
echo "The first argument is: $1"
echo "The second argument is: $2"
执行上述脚本并传递两个参数,输出结果为:
The first argument is: arg1
The second argument is: arg2
$@
这个变量表示所有的位置参数。它将所有传递给脚本或命令的参数看作一个整体,可以使用循环来遍历所有参数。
#!/bin/bash
echo "All arguments are: $@"
执行上述脚本并传递三个参数,输出结果为:
All arguments are: arg1 arg2 arg3
可以将$@
用于循环中,以便遍历所有位置参数:
#!/bin/bash
for arg in "$@"
do
echo "Argument: $arg"
done
执行上述脚本并传递三个参数,输出结果为:
Argument: arg1
Argument: arg2
Argument: arg3
$#
这个变量表示位置参数的个数,不包括脚本或命令本身的名称。
#!/bin/bash
echo "The number of arguments is: $#"
执行上述脚本并传递三个参数,输出结果为:
The number of arguments is: 3
$?
这个变量表示上一个命令的退出状态码。如果命令执行成功,则其值为0;如果命令执行失败,则其值为非零。
#!/bin/bash
ls /notexist
echo "The exit status of the previous command is: $?"
执行上述脚本,由于ls /notexist
命令找不到指定目录,其退出状态码为1,因此输出结果为:
ls: cannot access '/notexist': No such file or directory
The exit status of the previous command is: 1
$$
这个变量表示当前脚本或命令的进程ID(PID)。它在脚本中可以用来标识当前进程的唯一性。
#!/bin/bash
echo "The PID of this script is: $$"
执行上述脚本,输出结果为:
The PID of this script is: 1234
$!
这个变量表示最后一个在后台运行的命令的进程ID。可以用来获取最后一个后台任务的PID。
#!/bin/bash
sleep 5 &
echo "The PID of the last background command is: $!"
执行上述脚本,由于sleep 5 &
命令被放到后台运行,其PID为1234,因此输出结果为:
The PID of the last background command is: 1234
$*
这个变量表示所有的位置参数作为单个字符串。它将所有参数解释成一个字符串,而不是一个数组。可以使用引号将其括起来,以保留参数之间的空格。
#!/bin/bash
echo "All arguments as a single string: $*"
执行上述脚本并传递三个参数,输出结果为:
All arguments as a single string: arg1 arg2 arg3
$IFS
这个变量表示内部字段分隔符(Internal Field Separator)。它定义了Shell将输入拆分成字段(或单词)的分隔符,默认情况下,它包含空格、制表符和换行符。
#!/bin/bash
echo "The default value of IFS is: '$IFS'"
IFS=":"
echo "After changing IFS to ':', it is: '$IFS'"
执行上述脚本,输出结果为:
The default value of IFS is: '
'
After changing IFS to ':', it is: ':'
$HOME
这个变量表示当前用户的主目录。
#!/bin/bash
echo "The home directory of the current user is: $HOME"
执行上述脚本,输出结果为:
The home directory of the current user is: /home/user
$PWD
这个变量表示当前工作目录的路径。
#!/bin/bash
echo "The current working directory is: $PWD"
执行上述脚本,输出结果为:
The current working directory is: /home/user
这些特殊变量可以在Shell脚本中使用,让你可以获取和处理各种信息,以及控制脚本的行为。通过利用这些变量,你可以编写更灵活、可配置的Shell脚本。
在Shell编程中,字符串是一个由字符组成的序列。Shell提供了多种方式来处理字符串,包括字符串拼接、提取子串、替换等操作。
字符串的定义
单引号:使用单引号'
可以定义一个单行字符串,其中的内容会被原样输出,不会进行变量替换和转义字符的解释。
str='Hello, World!'
双引号:使用双引号"
可以定义一个单行字符串,其中的内容可以包含变量、转义字符和命令替换。
name='Alice'
str="Hello, $name!"
Here文档:使用Here文档可以定义包含多行内容的字符串,可以使用任意的定界符。
str=$(cat <<EOF
Hello,
World!
EOF
)
字符串拼接
使用连接操作符.
可以将两个字符串拼接在一起。
str1='Hello,'
str2=' World!'
result=$str1$str2
echo $result # 输出:Hello, World!
字符串长度
使用${#string}
可以获取字符串的长度。
str='Hello, World!'
len=${#str}
echo $len # 输出:13
子串提取
从左边开始提取指定长度的子串:${string:start:length}
str='Hello, World!'
sub=${str:0:5}
echo $sub # 输出:Hello
从右边开始提取指定长度的子串:${string:start-length}
str='Hello, World!'
sub=${str:7-5:5}
echo $sub # 输出:World
字符串替换
替换第一个匹配的子串:${string/substring/replacement}
str='Hello, World!'
new_str=${str/World/China}
echo $new_str # 输出:Hello, China!
替换所有匹配的子串:${string//substring/replacement}
str='Hello, World!'
new_str=${str//o/O}
echo $new_str # 输出:HellO, WOrld!
字符串切割为数组
使用IFS(内部字段分隔符)将字符串切割为数组。
str='apple,banana,cherry'
IFS=',' read -ra arr <<< "$str"
echo ${arr[1]} # 输出:banana
字符串比较
使用=
、!=
、>
、<
等符号进行字符串比较。
str1='apple'
str2='banana'
if [[ $str1 == $str2 ]]; then
echo 'Equal'
else
echo 'Not equal' # 输出:Not equal
fi
在Shell中,#*
和%*
是用于字符串处理的特殊符号,用于匹配和删除字符串中的特定模式。
#*
:
语法:${variable#*pattern}
功能:从变量${variable}
的开头开始,删除第一个匹配pattern
的字符串及其左边的内容,返回剩余的部分。
示例:
str="Hello, World!"
echo ${str#*o} # 输出:llo, World!
在这个示例中,${str#*o}
会删除str
变量中第一个匹配字母o
及其左边的所有字符,返回剩余的部分llo, World!
。
%*
:
语法:${variable%pattern*}
功能:从变量${variable}
的结尾开始,删除最后一个匹配pattern
的字符串及其右边的内容,返回剩余的部分。
示例:
str="Hello, World!"
echo ${str%o*} # 输出:Hello, W
在这个示例中,${str%o*}
会删除str
变量中最后一个匹配字母o
及其右边的所有字符,返回剩余的部分Hello, W
。
这些是Shell中处理字符串的一些常用操作和技巧。通过灵活运用这些操作,可以对字符串进行各种处理和转换,从而实现复杂的逻辑和功能。
在Shell脚本中,数组是一种特殊的变量类型,用于存储一组相关的值。Shell支持一维数组,即只能存储一列值。
声明数组:
语法:array_name=(value1 value2 ... valuen)
示例:
fruits=("apple" "banana" "orange")
在这个示例中,我们声明了一个名为fruits
的数组,并初始化了三个元素"apple"
、"banana"
和"orange"
。
读取数组元素:
语法:${array_name[index]}
示例:
echo ${fruits[0]} # 输出:apple
数组元素可以通过索引(从0开始)来访问。${fruits[0]}
表示fruits
数组中的第一个元素。
修改数组元素:
语法:array_name[index]=new_value
示例:
fruits[1]="grape"
echo ${fruits[1]} # 输出:grape
fruits[1]="grape"
将fruits
数组中索引为1的元素修改为"grape"
。
获取数组长度:
语法:${#array_name[@]}
示例:
length=${#fruits[@]}
echo $length # 输出:3
${#fruits[@]}
返回fruits
数组的长度,即元素的个数。
遍历数组:
示例:
for fruit in ${fruits[@]}; do
echo $fruit
done
这个示例中,通过for
循环遍历fruits
数组的所有元素,并逐个输出。
添加新元素到数组:
示例:
shell复制代码fruits+=("pear")
echo ${fruits[@]} # 输出:apple banana orange grape pear
通过使用+=
操作符,可以向数组末尾添加新的元素。
删除数组元素:
示例:
shell复制代码unset fruits[1]
echo ${fruits[@]} # 输出:apple orange grape
使用unset
命令可以删除数组中指定索引位置的元素。
切片数组:
示例:
shell复制代码echo ${fruits[@]:1:2} # 输出:orange grape
${fruits[@]:1:2}
表示从索引为1的位置开始,取2个元素,形成切片数组。
数组在Shell脚本中用于存储多个相关的值,可以方便地进行数据的组织和处理。通过索引访问、修改元素,获取数组长度以及遍历数组等操作,可以灵活地操作和处理数组中的数据。