shell命令
- Shell 自带的命令称为内置命令,它在 Shell 内部可以通过函数来实现,当 Shell 启动后,这些命令所对应的代码(函数体代码)也被加载到内存中,所以使用内置命令是非常快速的。本质上就是一个自带的函数
- 更多的命令是外部的应用程序,一个命令就对应一个应用程序。运行外部命令要开启一个新的进程,所以效率上比内置命令差很多,本质上就是一个应用程序。
- 用户输入一个命令后,Shell 先检测该命令是不是内置命令,如果是就执行,如果不是就检测有没有对应的外部程序:有的话就转而执行外部程序,执行结束后再回到 Shell;没有的话就报错,告诉用户该命令不存在。
**内置命令:**内置命令不宜过多,过多的内置命令会导致 Shell 程序本身体积膨胀,运行 Shell 程序后就会占用更多的内存。Shell 是一个常驻内存的程序,占用过多内存会影响其它的程序。只有那些最常用的命令才有理由成为内置命令,比如 cd、kill、echo 等。
**外部命令:**使用 echo 命令输出 PATH 变量的值,该变量就保存了 Shell 对外部命令的查找路径。
swiler@swiler-VirtualBox:~$ echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin
应用程序转成shell外部命令操作
创建hello.c文件,
gcc 命令 | 用来编译C和C++文件-c 编译、汇编而不链接 |
---|---|
-S | 编译而不进行汇编和链接 |
-E | 预处理 |
-v | 同时显示编译器的代码 |
-o <文件> | 将输出输入到指定文件 |
-x <语言> | 指定语言 |
–help | 显示帮助信息 |
–version | 显示版本信息 |
没有安装gcc,安装就行,进行$ sudo apt install gcc操作
安装完执行gcc输出,可看到hello文件输出
将hello转移至
这样就将一个应用程序转换成了shell外部命令操作。
具体步骤如下:
# hello_world.c文件内容是
vim hello_world.c
#按i ,进入输入模式
#include
int main ()
{
printf(“Hello World “);
return 0;
}
# 按ESC 之后 :wq 保存退出
# 编译 然后将输出输入到hello文件中
gcc -o hello hello_world.c
# 执行
./hello
# 显示内容:Hello World
合法的shell解析器
四种:sh/ bash/ rbash/ dash
查看sh解析器
编写一个shell脚本
#创建shell脚本
swiler@swiler-VirtualBox:~$ sudo vi hello.sh
#在文件内
#!/bin/bash
echo "hello,world!"
#修改文件权限
swiler@swiler-VirtualBox:~$ sudo chmod 777 hello.sh
#查看目录
swiler@swiler-VirtualBox:~$ ll
#可观察到
-rwxrwxrwx 1 root root 33 2月 12 09:44 hello.sh*
#启动,如下4种启动方式
shell启动方式
4种启动方式,在环境变量上有所区别,现在暂不深究
shell脚本语法
变量相关操作
定义变量
- variable=value
#在vi编辑器内#
#指定shell脚本所使用的解析器
#!/bin/bash
#定义一个变量,直接赋值,等号左右不能有空格,适用于变量的值没有空格或字符的情况
var=1234
#加$符号使用变量,用echo直接输出
echo "$var"
执行,终端输出1234
- variable=‘value’
#在vi编辑器内#
#指定shell脚本所使用的解析器
#!/bin/bash
#定义一个变量,单引号括住,等号左右不能有空格
var='123 454'
#加$符号使用变量,用echo直接输出
echo "$var"
执行,终端输出123 454
- variable=“value”
#在vi编辑器内#
#指定shell脚本所使用的解析器
#!/bin/bash
#定义一个变量,双引号括住,等号左右不能有空格
var="123 454"
#定义一个变量,双引号括住,等号左右不能有空格
var1="${var}abcd"
#加$符号使用变量,用echo直接输出
echo "$var1"
##如果将var1="${var}abcd"改为var1='${var}abcd',则输出内容为${var}abcd##
执行,终端输出123 454abcd
注意单引号和双引号的区别,单引号内的内容是所见即所得,即单引号内的东西全当字符输出;双引号能够区分出对其它变量的引用。
使用变量
- $variable
- ${variable}
将命令的结果赋值给变量
- variable=`command`
#!/bin/bash
var=`pwd`
echo "$var"
#执行 pwd 指令可立刻得知目前所在的工作目录的绝对路径名称。
- variable=$(command)
#!/bin/bash
var=$(pwd)
echo "$var"
删除变量
- unset
#!/bin/bash
var="123 454"
var1="star"
echo "${var1}${var}"
#没有unset var前两个变量都输出
unset var
#unset var后,var变量不输出,只输出var1
echo "${var1}${var}"
特殊变量
变量 | 含义 |
---|---|
$0 | 当前脚本的文件名。 |
$n(n≥1) | 传递给脚本或函数的参数。n 是一个数字,表示第几个参数。例如,第一个参数是 $1,第二个参数是 $2。 |
$# | 传递给脚本或函数的参数个数。 |
$* | 传递给脚本或函数的所有参数。 |
$@ | 传递给脚本或函数的所有参数。当被双引号" " 包含时,$@ 与 $* 稍有不同. |
$? | 上个命令的退出状态或者获取函数返回值。 |
$$ | 当前 Shell 进程 ID。对于 Shell 脚本,就是这些脚本所在的进程 ID。 |
#!/bin/bash
var="123 454"
var1="star"
echo "${var1}${var}" #引用并输出变量
unset var
echo "${var1}${var}" #引用并输出变量
echo "$0" #当前脚本的文件名
echo "$1" #传递给脚本或函数的参数$1,在控制台赋值
echo "$2" #传递给脚本或函数的参数$2,在控制台赋值
echo "$#" #传递给脚本或函数的参数个数
echo "$*" #传递给脚本或函数的所有参数
echo "$@" #传递给脚本或函数的所有参数
echo "$?" #上个命令的退出状态或者获取函数返回值
echo "$$" #当前 Shell 进程 ID
exit 11 #设定函数返回值
输出结果:
字符串拼接
并排放
#!/bin/bash
var="star "
var1=${var}sun #字符串拼接
echo ${var1}
#或者这么输出:echo "$var1"
#或者这么输出:echo "${var1}"
读取从键盘输入的数据
read
#!/bin/bash
read -p "input a:" a
read -p "input b:" b
echo "${a}"
echo "${b}"
执行结果:
退出当前进程
exit
对整数进行数学运算
(())
#!/bin/bash
#输入a和b的值
read -p "input a:" a
read -p "input b:" b
#执行a+b并赋值给var
var=$(( a+b ))
#输出var到控制台
echo "${var}"
执行结果:
逻辑与/或
command1 && command2
command1 || command2
检测某个条件是否成立
test expression 和 [ expression ]
选 项 | 作 用(0为真,1为假) |
---|---|
-eq | 判断数值是否相等 |
-ne | 判断数值是否不相等 |
-gt | 判断数值是否大于 |
-lt | 判断数值是否小于 |
-ge | 判断数值是否大于等于 |
-le | 判断数值是否小于等于 |
-z str | 判断字符串 str 是否为空 |
-n str | 判断字符串str是否为非空 |
=和== | 判断字符串str是否相等 |
-d filename | 判断文件是否存在,并且是否为目录文件。 |
-f filename | 判断文件是否存在,井且是否为普通文件。 |
#!/bin/bash
read -p "input a:" a
read -p "input b:" b
echo "0 is true,1 is false"
#判断数值是否相等
echo "test -eq a&&b"
test $a -eq $b && echo "a=b"
#判断数值是否不相等
echo "test -eq a||b"
test $a -eq $b || echo "a!=b"
#判断数值是否不相等
echo "test -ne"
test $a -ne $b && echo "a!=b"
#判断数值是否大于
echo "test -gt"
test $a -gt $b && echo "a>b"
#判断数值是否小于
echo "test -lt"
test $a -lt $b && echo "a<b"
#判断数值是否大于等于
echo "test -ge"
test $a -ge $b && echo "a>=b"
#判断数值是否小于等于
echo "test -le"
test $a -le $b && echo "a<=b"
a>b / a<b / a=b
判断文件是否存在,并且是否为目录文件
#!/bin/bash
read -p "input a:" a
[ -d $a ] && echo "${a}"
判断文件是否存在,并且是否为普通文件
#!/bin/bash
read -p "input a:" a
[ -f $a ] && echo "${a}"
管道
定义
一般我们在进行操作的时候,命令很多,但我们只想要其中一部分,那么就可以使用管道了。
管道是Linux中很重要的一种通信方式,是把一个前一个结果的输出直接连接到另一个的输入,通常和grep合作使用。
**命令:**command1 | command2
if语句
if语句
if condition
then
statement(s)
fi
if else 语句
if condition
then
statement1
else
statement2
fi
if elif else 语句
if condition1
then
statement1
elif condition2
then
statement2……
else
statementn
fi
#!/bin/bash
#输入a和b
read -p "input a:" a
read -p "input b:" b
if [ $a -eq $b ] #如果a=b
then
echo "a=b"
elif [ $a -gt $b ] #如果a>b
then
echo "a>b"
else #如果a<b
echo "a<b"
fi
case in语句
case expression in
pattern1)
statement1
;;
pattern2)
statement2
;;
pattern3)
statement3
;;
……
*)
statementn
esac
#!/bin/bash
read -p "input a:" a
case $a in
1)
echo "a=1"
;;
2)
echo "a=2"
;;
3)
echo "a=3"
;;
*)
echo "a=other"
;;
esac
输出结果:
for in 循环
for variable in value_list
do
statements
done
value_list 的取值
- 直接给出具体的值
- 给出一个取值范围
#!/bin/bash
#read -p "input a:" a
#read -p "input b:" b
for n in {1..10}
do
echo "$n"
done
#效果同上
#for n in 1,2,3,4,5,6,7,8,9,10
#do
# echo "$n"
#done
结果:输出1~10,十个数。
- 使用命令的执行结果
- 使用 Shell 通配符
#!/bin/bash
#read -p "input a:" a
#read -p "input b:" b
for n in $(ls /bin/*sh)
do
echo "$n"
done
#bin目录下的shell解析器遍历出来
结果
- 使用特殊变量 $*
#!/bin/bash
#read -p "input a:" a
#read -p "input b:" b
for n in $*
#或for n in $@
#或for n in "$@"
do
echo "$n"
done
结果:
- 使用特殊变量 “$*”
#!/bin/bash
#read -p "input a:" a
#read -p "input b:" b
for n in "$*"
do
echo "$n"
done
结果:
while 循环
while condition
do
statements
done
#!/bin/bash
n=0
while (( n < 10))
do
echo "${n}"
n=$((n+1))
done
结果:
定义函数
function name() {
statements
[return value]
}
#!/bin/bash
#定义一个函数
function my_name(){
echo "swiler"
}
#调用该函数
my_name