linux shell学习笔记

shell 命令提示符

不同的 Linux 发行版使用的提示符格式大同小异,例如在 CentOS 中,默认的提示符类似下面这样:
[mozhiyan@localhost ~]$

各个部分的含义如下:
[]是提示符的分隔符号,没有特殊含义。
mozhiyan表示当前登录的用户,我现在使用的是 mozhiyan 用户登录。
@是分隔符号,没有特殊含义。
localhost表示当前系统的简写主机名(完整主机名是 localhost.localdomain)。
~代表用户当前所在的目录为主目录(home 目录)。如果用户当前位于主目录下的 bin 目录中,那么这里显示的就是bin。
$是命令提示符。Linux 用这个符号标识登录的用户权限等级:如果是超级用户(root 用户),提示符就是#;如果是普通用户,提示符就是$。

什么是主目录?

Linux 系统是纯字符界面,用户登录后,要有一个初始登录的位置,这个初始登录位置就称为用户的主目录(home 目录)。超级用户的主目录为/root/,普通用户的主目录为/home/用户名/。

第二层命令提示符

有些命令不能在一行内输入完成,需要换行,这个时候就会看到第二层命令提示符。第二层命令提示符默认为>,请看下面的例子:
[mozhiyan@localhost ~]$ echo "Shell教程"
Shell教程
[mozhiyan@localhost ~]$ echo "
> http://
> c.biancheng.net
> "

http://
c.biancheng.net

第一个 echo 命令在一行内输入完成,不会出现第二层提示符。第二个 echo 命令需要多行才能输入完成,提示符>用来告诉用户命令还没输入完成,请继续输入。

Shell四种运行方式(启动方式)

Shell配置文件(配置脚本)的加载

与 Bash Shell 有关的配置文件主要有 /etc/profile、~/.bash_profile、~/.bash_login、~/.profile、~/.bashrc、/etc/bashrc、/etc/profile.d/*.sh,不同的启动方式会加载不同的配置文件。


登录式的 Shell

Bash 官方文档说:如果是登录式的 Shell,首先会读取和执行 /etc/profiles,这是所有用户的全局配置文件,接着会到用户主目录中寻找 ~/.bash_profile、~/.bash_login 或者 ~/.profile,它们都是用户个人的配置文件。

不同的 Linux 发行版附带的个人配置文件也不同,有的可能只有其中一个,有的可能三者都有,笔者使用的是 CentOS 7,该发行版只有 ~/.bash_profile,其它两个都没有。

如果三个文件同时存在的话,到底应该加载哪一个呢?它们的优先级顺序是 ~/.bash_profile > ~/.bash_login > ~/.profile。

如果 ~/.bash_profile 存在,那么一切以该文件为准,并且到此结束,不再加载其它的配置文件。

如果 ~/.bash_profile 不存在,那么尝试加载 ~/.bash_login。~/.bash_login 存在的话就到此结束,不存在的话就加载 ~/.profile。

注意,/etc/profiles 文件还会嵌套加载 /etc/profile.d/*.sh,请看下面的代码:
for i in /etc/profile.d/*.sh ; do
    if [ -r "$i" ]; then
        if [ "${-#*i}" != "$-" ]; then
            . "$i"
        else
            . "$i" >/dev/null
        fi
    fi
done

同样,~/.bash_profile 也使用类似的方式加载 ~/.bashrc:
if [ -f ~/.bashrc ]; then
. ~/.bashrc
fi
非登录的 Shell

如果以非登录的方式启动 Shell,那么就不会读取以上所说的配置文件,而是直接读取 ~/.bashrc。

~/.bashrc 文件还会嵌套加载 /etc/bashrc,请看下面的代码:
if [ -f /etc/bashrc ]; then
. /etc/bashrc
fi




#!/bin/bash
url="http://c.biancheng.net"
website1='C语言中文网:${url}'
website2="C语言中文网:${url}"
echo $website1
echo $website2

运行结果:
C语言中文网:${url}
C语言中文网:http://c.biancheng.net

以单引号' '包围变量的值时,单引号里面是什么就输出什么,即使内容中有变量和命令(命令需要反引起来)也会把它们原样输出。这种方式比较适合定义显示纯字符串的情况,即不希望解析变量、命令等的场景。


将命令的结果赋值给变量

Shell 也支持将命令的执行结果赋值给变量,常见的有以下两种方式:
variable=`command`
variable=$(command)

export a这种形式是在定义变量 a 以后再将它导出为环境变量,如果想在定义的同时导出为环境变量,可以写作export a=22。

命令替换 $()和``

Shell 命令替换是指将命令的输出结果赋值给某个变量。比如,在某个目录中输入 ls 命令可查看当前目录中所有的文件,但如何将输出内容存入某个变量中呢?这就需要使用命令替换了,这也是 Shell 编程中使用非常频繁的功能。

注意:有些情况必须使用 $():$() 支持嵌套,反引号不行。

Shell 中有两种方式可以完成命令替换,一种是反引号` `,一种是$(),使用方法如下:
variable=`commands`
variable=$(commands)

data 命令的%s格式控制符可以得到当前的 UNIX 时间戳,
#!/bin/bash
begin_time=`date +%s`    #开始时间,使用``替换
sleep 20s                #休眠20秒
finish_time=$(date +%s)  #结束时间,使用$()替换
run_time=$((finish_time - begin_time))  #时间差
echo "begin time: $begin_time"
echo "finish time: $finish_time"
echo "run time: ${run_time}s"

运行脚本,20 秒后可以看到输出结果:
begin time: 1555639864
finish time: 1555639884
run time: 20s

Shell数学计算(算术运算,加减乘除运算)

第 6 行代码中的(( ))是 Shell 数学计算命令。和 C++、C#、Java 等编程语言不同,在 Shell 中进行数据计算不那么方便,必须使用专门的数学计算命令,(( ))就是其中之一。更多细节我们将会在《Shell数学计算》一节中详细讲解。

Shell (( )) 的用法
双小括号 (( )) 的语法格式为:
((表达式))

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

表达式可以只有一个,也可以有多个,多个表达式之间以逗号,分隔。对于多个表达式的情况,以最后一个表达式的值作为整个 (( )) 命令的执行结果。
可以使用$获取 (( )) 命令的结果,这和使用$获得变量值是类似的。
在 (( )) 中使用变量无需加上$前缀,(( )) 会自动解析变量名,这使得代码更加简洁,也符合程序员的书写习惯。

let 命令和双小括号 (( )) 的用法是类似的,它们都是用来对整数进行运算,读者已经学习了《Shell (())》,再学习 let 命令就相当简单了。


用$[]
a=$[1+2]
echo $a

在这里插入图片描述

Shell特殊变量 $* @ 、 @、 @?、$$

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

shell ∗ 与 *与 @的区别

Shell字符串截取

获取字符串长度

在 Shell 中获取字符串长度很简单,具体方法如下:
${#string_name}```

从指定位置开始截取
1) 从左边开始计数
${string: start :length}
其中,string 是要截取的字符串,start 是起始位置(从左边开始,从 0 开始计数),length 是要截取的长度(省略的话表示直到字符串的末尾)。
url="c.biancheng.net"
echo ${url: 2: 9}

2) 从右边开始计数
${string: 0-start :length}
url="c.biancheng.net"
echo ${url: 0-13: 9}
结果为biancheng。从右边数,b是第 13 个字符。

从左边开始计数时,起始数字是 0(这符合程序员思维);从右边开始计数时,起始数字是 1(这符合常人思维)。计数方向不同,起始数字也不同。

Linux bc命令:一款数学计算器

Shell test命令(Shell [])详解,附带所有选项及说明

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

#!/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

1) 与文件检测相关的 test 选项
文件类型判断
选 项	作 用
-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 号一致,可以理解为两个文件是否为同一个文件。这个判断用于判断硬链接是很好的方法

2) 与数值比较相关的 test 选​项
表2:test 数值比较相关选项列表
选 项	作 用
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。

不管是比较数字还是字符串,Shell 都不支持 >= 和 <= 运算符,切记。

3) 与字符串判断相关的 test 选项
选 项	作 用
-z str	判断字符串 str 是否为空。
-n str	判断宇符串 str 是否为非空。
str1 = str2
str1 == str2	=和==是等价的,都用来判断 str1 是否和 str2 相等。
str1 != str2	判断 str1 是否和 str2 不相等。
str1 \> str2	判断 str1 是否大于 str2。\>是>的转义字符,这样写是为了防止>被误认为成重定向运算符。
str1 \< str2	判断 str1 是否小于 str2。同样,\<也是转义字符。

在这里插入图片描述

4) 与逻辑运算相关的 test 选项
选 项	作 用
expression1 -a expression	逻辑与,表达式 expression1 和 expression2 都成立,最终的结果才是成立的。
expression1 -o expression2	逻辑或,表达式 expression1 和 expression2 有一个成立,最终的结果就成立。
!expression	逻辑非,对 expression 进行取反。

#!/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

Shell [[]]详解:检测某个条件是否成立
[[ ]]是 Shell 内置关键字,它和 test 命令类似,也用来检测某个条件是否成立。

test 能做到的,[[ ]] 也能做到,而且 [[ ]] 做的更好;test 做不到的,[[ ]] 还能做到。可以认为 [[ ]] 是 test 的升级版,对细节进行了优化,并且扩展了一些功能。

多个表达式进行逻辑运算 三种方式
[ -z "$str1" ] || [ -z "$str2" ]

[ -z "$str1" -o -z "$str2" ]

[[ -z $str1 || -z $str2 ]]

注意,[[ ]] 剔除了 test 命令的-o和-a选项,你只能使用 || 和 &&。这意味着,不能写成下面的形式:
[[ -z $str1 -o -z $str2 ]]

当然,使用逻辑运算符将多个 [[ ]] 连接起来依然是可以的
[[ -z $str1 ]] || [[ -z $str2 ]]



在这里插入图片描述
[[ ]] 支持正则表达式

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

str 表示字符串,regex 表示正则表达式。

下面的代码检测一个字符串是否是手机号:
纯文本复制
#!/bin/bash
read tel
if [[ $tel =~ ^1[0-9]{10}$ ]]
then
    echo "你输入的是手机号码"
else
    echo "你输入的不是手机号码"
fi

Linux Shell重定向(输入输出重定向)

Linux 中一切皆文件,包括标准输入设备(键盘)和标准输出设备(显示器)在内的所有计算机硬件都是文件。
为了表示和区分已经打开的文件,Linux 会给每个文件分配一个 ID,这个 ID 就是一个整数,被称为文件描述符(File Descriptor)。
在这里插入图片描述

stdin、stdout、stderr 默认都是打开的,在重定向的过程中,0、1、2 这三个文件描述符可以直接使用。

Linux Shell 输出重定向
输出重定向是指命令的结果不再输出到显示器上,而是输出到其它地方,一般是文件中。这样做的最大好处就是把命令的结果保存起来,当我们需要的时候可以随时查询。Bash 支持的输出重定向符号如下表所示。
在这里插入图片描述
在输出重定向中,>代表的是覆盖,>>代表的是追加。
注意:
输出重定向的完整写法其实是fd>file或者fd>>file,其中 fd 表示文件描述符,如果不写,默认为 1,也就是标准输出文件。

当文件描述符为 1 时,一般都省略不写,如上表所示;当然,如果你愿意,也可以将command >file写作command 1>file,但这样做是多此一举。

当文件描述符为大于 1 的值时,比如 2,就必须写上。

需要重点说明的是,fd和>之间不能有空格,否则 Shell 会解析失败;>和file之间的空格可有可无。为了保持一致,我习惯在>两边都不加空格。

下面的语句是一个反面教材:
echo “c.biancheng.net” 1 >log.txt

注意1和>之间的空格。echo 命令的输出结果是c.biancheng.net,我们的初衷是将输出结果重定向到 log.txt,但是当你打开 log.txt 文件后,发现文件的内容为c.biancheng.net 1,这就是多余的空格导致的解析错误。也就是说,Shell 将该条语句理解成了下面的形式:
echo “c.biancheng.net” 1 1>log.txt

如果你既不想把命令的输出结果保存到文件,也不想把命令的输出结果显示到屏幕上,干扰命令的执行,那么可以把命令的所有结果重定向到 /dev/null 文件中。如下所示:
ls -l &>/dev/null
大家可以把 /dev/null 当成 Linux 系统的垃圾箱,任何放入垃圾箱的数据都会被丢弃,不能恢复。

Linux Shell 输入重定向
输入重定向就是改变输入的方向,不再使用键盘作为命令输入的来源,而是使用文件作为命令的输入。
在这里插入图片描述

和输出重定向类似,输入重定向的完整写法是fd<file,其中 fd 表示文件描述符,如果不写,默认为 0,也就是标准输入文件。

使用输入重定向符号<<,这个符号的作用是使用特定的分界符作为命令输入的结束标志,而不使用 Ctrl+D 键。

[c.biancheng.net]$ wc -l <<END
> 123
> 789
> abc
> xyz
> END
4
wc 命令会一直等待用输入,直到遇见分界符 END 才结束读取。

Shell进程替换

Shell进程替换的本质
为了能够在不同进程之间传递数据,实际上进程替换会跟系统中的文件关联起来,这个文件的名字为/dev/fd/n(n 是一个整数)。该文件会作为参数传递给()中的命令,()中的命令对该文件是读取还是写入取决于进程替换格式是<还是>:
如果是>(),那么该文件会给()中的命令提供输入;借助输出重定向,要输入的内容可以从其它命令而来。
如果是<(),那么该文件会接收()中命令的输出结果;借助输入重定向,可以将该文件的内容作为其它命令的输入。

SHELL脚本中command -v 用法
在Linux中,command -v 可以判断一个命令是否支持

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值