shell用法大全

文章目录

基本介绍

  • 执行/etc/profile
  • 执行/etc/profile.d/.sh
  • 执行~/.bash_porfile
  • 执行~/.bashrc
  • 执行/etc/bashrc

操作文件目录

列出文件(ls命令)

ls命令存在如下常用参数

参数意义
-F判断列出的是文件还是目录
-l列出文件的详细信息,包括权限,大小(byte单位,如果想要更友好可以-lh),最后修改时间
-a同时显示隐藏文件和目录
-t按照最后修改时间排序
-r在原来的基础上倒序

获取当前目录(pwd命令)

获取当前用户所在的目录命令:pwd

有个需求,已知文件的路径,想获得文件名或者文件所在的目录名
可以使用basename和dirname命令

#!/bin/bash
path="/root/dexuan/server.py"
echo $path
echo "basename:$(basename $path)"
echo "dirname:$(dirname $path)"

结果:

/root/dexuan/server.py
basename:server.py
dirname:/root/dexuan

查看文件内容(cat,more,less,head,tail)

cat命令

cat可以跟上多个文件名字,将内容进行拼接后打印到终端

cat [option] [file]

参数意义
-n显示行号
-b只给非空行添加标号

more和less命令

有时候文件内容太多,使用cat命令就不合适,使用more和less命令都可以实现分页查看。

区别:

  • more:只能用空格键一页一页显示文件内容,直到文件结束,more命令退出
  • less:可以按PageUp或者PageDowm或者上下方向键来回反复浏览文见内容,Q退出

head和tail命令

如果我们只关心文件内容的开头和结尾,就可以使用head和tail命令

参数意义
-n限制输出行数
-c限制输出字节数
-f动态展示内容

统计文件行数和字数(wc)

wc test.sh

输出:

5  10 119 test.sh

第一列是行数,第二列是字数,第三列是字节数

|–|--|
| -l | 只统计行数 |
| -w |只统计字数 |
| -c | 只统计字节数|

创建文件和目录(touch,mkdir)

创建文件夹:

  1. 可以直接使用vim命令创建
  2. touch命令创建

创建目录:

mkdir命令,最常用的就是-p选项,递归创建

mkdir -p /root/dexuan/test

删除文件和目录(rm)

最常用的,rm -rf ./test.sh

重命名文件和目录(mv)

mv souce dist

例子:将当前目录test.sh重命名为t.sh

mv ./test.sh t.sh

移动文件和目录(mv)

同样是mv命令,但是要注意一点,假如说你要移动的文件或者文件夹与目的地的文件或者文件夹存在重名,就会直接覆盖,可以给mv加个-i参数,重名时候会提示。

建立文件和目录的链接(mv)

可以把链接理解成快捷方式。
具体命令如下:

ln -s 源文件名称 软链接文件名称

例子:

ln -s ./souce ./souce_link
cd souce_link
pwd -L
pwd -P

pwd -L 会打印出逻辑地址,即./souce_link
pwd -P会显示物理地址,即./souce

复制文件和目录(cp)

命令和mv格式基本一致

cp souce dist

如果想移动目录,就需要加-r参数

cp -r souce dist

权限控制(chmod)

linux一共存在3种权限,分别是读,写,执行

以以下命令为例:

[root@i-zd7on5h0 ~]# ls -l
total 16572
drwxr-xr-x  3 root root     4096 Dec 20 22:53 dexuan
drwxr-xr-x 19  501  501     4096 Dec  1 23:41 Python-3.7.1
-rw-r--r--  1 root root 16960060 Oct 20  2018 Python-3.7.1.tar.xz

drwxr-xr-x

  • 第一个d代表目录
  • 2-4代表文件所有者的权限
  • 5-7代表文件所属组的权限
  • 8-10代表文件所有者的权限

drwxr-xr-x代表着是一个文件夹,root用户对其有读写执行权限,root用户组内其他成员对其只有读和执行权限,非该用户组的用户也有读和执行权限

如何修改文件或者目录权限呢?
在这里插入图片描述
例子:

chmod 755 test.py

修改test.py文件权限,root用户对其有读写执行权限,root用户组内其他成员对其只有读和执行权限,非该用户组的用户也有读和执行权限

输入输出重定向和管道

linux最重要的设计思想就是一切皆文件,如显示屏幕是个设备文件,网络连接也是一个文件。linux运行的每一个进程都会默认关联到3个打开的文件上,他们是:标准输入,标准输出,以及错误输出

重定向(覆盖)

linux中重定向输出的格式是

command >outputfile

如果outputfile存在,就会覆盖掉原来的内容

ls >test.txt

把ls输出的内容重定向到test.txt文件中

重定向(追加)

linux中重定向输出的格式是

command >>outputfile

如果outputfile存在,就会追加输出内容到文件末尾

标准输入

read online <test.txt

这句话的意思是将test.txt的一行输入到变量online中

例子:
test.txt内容如下,要求打印文件的每一行

[root@i-zd7on5h0 dexuan]# cat test.txt 
hello
dexuan

echo.sh

#!/bin/bash
  
read oneline
while [ "$oneline" != "" ]
do
echo "$oneline"
read oneline
done

exit 0

输出:

[root@i-zd7on5h0 dexuan]# ./echo.sh <test.txt 
hello
dexuan

标准错误输出

指定输出到标准错误输出代码如下

echo "errormsg" > &2

重定向代码如下:

./echo2.sh >standard.out 2>error.err

此时会把进程标准输出重定向到standard.out,错误输出重定向到error.err

例子:
下面是echo2.sh代码

#!/bin/bash

echo "error" >&2
echo "print" >&1

输出如下:`

./echo2.sh 
error
print
[root@i-zd7on5h0 dexuan]# ./echo2.sh >standard.out 2>error.err
[root@i-zd7on5h0 dexuan]# cat standard.out 
print
[root@i-zd7on5h0 dexuan]# cat error.err 
error
[root@i-zd7on5h0 dexuan]# 

如果想要将正常和错误的重定向内容全部放在一个文件中,可以这样:

./echo2.sh >standard.out 2>&1

管道

一个程序的标准输出想作为下个程序的输入,那该怎么办呢,可以使用管道符处理

命令1 | 命令2

注意,下一个命令需要是读取标准输入流进行处理的命令,管道才能生效,如less, more, head, tail 等都是可以接受 standard input 的管线命令,ls, cp, mv 等就不是管线命令。

文件描述符

文件描述符,可以理解成符号与文件的映射关系,系统自带的3个文件描述符,stdin:0,stdout:1,stderr:2,其他的需要自己定义。

定义:

echo "output" >4&

意思是这段话输出到文件描述符为4的文件中。

此时只需要定义文件即可,加入上述脚本存在test.sh中,那么可以定义下面命令:

./test.sh 4>out.txt

把文件描述符为4的输出,输出到out.txt

进程

进程查看

https://www.cnblogs.com/fakerbin/p/6513365.html

jobs命令,查看后台进程命令

前台进程与后台进程

  • 一个进程占据了整个终端,叫做前台进程
  • 进程启动后不占据终端,终端可以继续执行命令

前台进程转后台进程

一般我们启动命令都是前台进程,假如我想创建后台进程,应该怎么办呢?可以使用&符号

如:

./start.sh &

就是将start.sh脚本后台运行
但是这样也有弊端,这个进程的标准输出或者标准错误输出会显示在终端上,这是我们不希望的,那么我们应该怎么办呢?重定向就起到作用了

./start.sh >output.txt 2>1& &

后台进程转前台进程

有时候后台进程需要标准输入,这时候程序就会阻塞等待标准输入,就需要将后台进程转到前台,此时fg命令就有用了

fg %工作号

工作号就是jobs命令查看后台进程编号

nohup

使用上面方式进行后台进程的启动会存在弊端,就是假如父进程退出了,子进程也会跟着被杀死。那么nohup命令就是解决这个问题的,当父进程退出后,nohup启动的命令会被init进程接管。具体命令如下:

nohup ./start.sh >output.txt 2>1& &

杀死进程

kill -9 pid

-9是参数,表示强制删除

最常见的是9和15
9) SIGKILL
用来立即结束程序的运行. 本信号不能被阻塞、处理和忽略。如果管理员发现某个进程终止不了,可尝试发送这个信号。
15) SIGTERM
程序结束(terminate)信号, 与SIGKILL不同的是该信号可以被阻塞和处理。通常用来要求程序自己正常退出,shell命令kill缺省产生这个信号。如果进程终止不了,我们才会尝试SIGKILL。

killall命令会杀死带有输入的所有进程

killall 进程名称

[root@localhost ~]# ps -ef|grep vi

root     17581 17398  0 17:51 pts/0    00:00:00 vi test.txt

root     17611 17582  0 17:51 pts/1    00:00:00 grep vi

[root@localhost ~]# ps -ef|grep vi

root     17581 17398  0 17:51 pts/0    00:00:00 vi test.txt

root     17640 17612  0 17:51 pts/2    00:00:00 vi test.log

root     17642 17582  0 17:51 pts/1    00:00:00 grep vi

[root@localhost ~]# killall vi

[root@localhost ~]# ps -ef|grep vi

root     17645 17582  0 17:52 pts/1    00:00:00 grep vi

字符串操作

cut命令

-b :以字节为单位进行分割。这些字节位置将忽略多字节字符边界,除非也指定了 -n 标志。
-c :以字符为单位进行分割。
-d :自定义分隔符,默认为制表符。
-f :与-d一起使用,指定显示哪个区域。

例如:
保留ls -l 每一行的第3-5个字符

ls -l | cut -b 3-5

结果:

[root@VM-101-190-centos ~]# ls -l | cut -b 3-5
tal
w-r
wxr
wxr
wxr
wxr
w-r
w-r
wxr

例2:

echo $PATH | cut -d ':' -f 1

根据:对字符串分割,留下第一个
结果:

/root/dexuantang/apache-maven-3.6.3/bin

paste命令

paste number.txt name.txt -d : 

将number.txt各行和name.txt各行进行拼接,拼接符为:

sort和uniq命令

  • sort 可针对文本文件的内容,以行为单位来排序
  • uniq 命令用于检查及删除文本文件中重复出现的行列,一般与 sort 命令结合使用

变量

定义变量

在shell中,定义变量直接就是

name=value

shell中没有变量类型,都是字符串
假如要把执行命令的标准输出流弄到变量中去

name=`命令`

例子:

name=`ls`

就是将ls输出的内容赋值到变量name中
如果想要输出变量,就可以使用$符号

name2=$name
echo "$name2"xxxxx

删除变量

unset命令用于删除变量或函数
可以删除普通变量,数组变量以及函数变量

数组变量

初始化数组一共有2种方法
第一种:

array[index]=value

第二种:

array=( v1 v2 v3 )

空格分开各个元素
如果指定某个值赋值给哪一个元素了,就可以用下面的方法

array=( [2]=v3 [0]=v1 [1]=v2 )

引用数组的方式如下:
引用数组某个值:

t=${array[0]}

引用数组所有列表并打印:

t=${array[@]}
for i in $t
do
	echo $i
done

本地变量和环境变量

  • 本地变量:shell启动子进程的时候,变量不会传递到子进程中。
  • 环境变量:创建子进程可以创建父进程中的

如何创建环境变量呢

export name=value
name=value;export

所有子进程可以使用父进程的环境变量,但不能修改父进程的环境变量

shell变量

当shell启动的时候,会初始化一些特殊变量。

  • HOME:当前用户主目录
  • SHELL:当前用户所使用的shell程序,如/bin/bash
  • USER:当前的登陆用户名
  • UID:扩展为当前用户数字的userid
  • BASH_VERSION:当前所使用的bash版本号
  • PWD:当前工作目录
  • OLDPWD:前一个工作目录,即执行cd命令以前所在的目录
  • SCECONDS:当前shell执行的时间
  • RANDOM:产生0-32767随机整数
  • PATH:环境变量

特殊变量

也就是参数变量

./test.sh param1 param2

test.sh内容

#!bin/bash
echo $#
echo $0
echo $1
echo $2

此时答应出来内容:
2
./test.sh
param1
param2
param1 param2

  • $# 代表参数个数
  • $@ 输出参数列表
  • $? 代表上一个命令是否执行成功,0就是成功
  • $$ 代表当前进程的pid

流程控制

条件分支

if list1
then
	list2
elif list3
then
	list4
else
	list5
fi

如果list1退出状态为0,说明这个分支触发成功。

list可以是条件表达式,对于数字的比较有以下几种

  • eq:等于
  • ne:不等于
  • -le:小雨等于
  • gt:大于
  • ge:大于等于

对于字符串的比较

  • == 两个字符串相等
  • != 两个字符串不相等

while循环

while 条件
do
	循环内容
done

for循环

for i in 列表
do
	循环内容
done
for (i=1;i<=100;i++)
do
	循环内容
done

break语句

break语句的基本语法为

break [n]

n可以忽略,如果忽略就是跳出最内层循环,如果n有值,就是跳出n层循环

continue语句

break语句的基本语法为

continue [n]

n可以忽略,如果忽略就是继续最内层循环,如果n有值,就是继续n层循环

变量替换

高级获取参数(getopts)命令

getopts optstring name [args]
  • optstring是选项
  • name 是放选项的变量
#!/usr/bin/env bash
# filename: getopts.sh
while getopts :abc:e:f:h argvs; do
  case $argvs in
    a) echo "这是执行-a的效果" ;;
    b) echo "这是执行-b的效果" ;;
    c) echo "这是执行-c的效果及参数值:${OPTARG}" ;;
    e) echo "这是执行-e的效果及参数值: ${OPTARG}" ;;
    h) echo "帮助信息"
    f) echo "这是-f的效果及参数值 ${OPTARG}" ;;
  [?]) echo "无效或不存在的选项" ;;
    :) echo "选项缺少参数" ;;
  esac
done
  • 第一个冒号 getopts 会区分 invalid option (无效选项) 错误和 miss option argument(丢失选项)错误。
  • while循环中每次都会执行getopts命令,每处理一个命令getopts会返回0,直到所有命令都处理完,返回1,退出循环。
  • getopts在处理每一个需要参数的选项时,都会把参数保存到变量OPTARG中。
  • 如果在getopts命令某个选项字符后面添加了冒号,说明该选项需要参数。

文件替换

常用通配符

通配符含义
*匹配0个或者多个任意字符
?匹配1个任意字段
[]匹配指定字符范围中任意一个字符

例子

ls ?.txt # 显示文件名以txt结束并且文件名只有1位的文件
ls [ab]* #显示文件名以a或者b起始的文件
ls [^ab]* #显示文件名不以a或者b起始的文件
ls [!ab]* #显示文件名不以a或者b起始的文件
ls [a-c]* #显示文件名以a或者b或者c起始的文件

命令替换

有时候希望一个命令中引用另一个命令的输出,这时候就需要用到命令替换。

$(commands)
`commands`

可以将命令赋值给变量,变量替换下一个命令
例子:

echo ls
echo $(ls)

第一个输出ls字符串,第二个输出ls命令的标准输出流

算数运算符替换

$((expression))

例子

echo $((3+2*4/8))

输出:4

引用

当命令中存在特殊字符时候,就需要被引用。
例子,当目录存在tmp*.txt文件时候,我们需要删除这个文件,这时候如果直接使用rm -rf tmp*.txt时候,命令把*当成通配符处理,会造成误删除。这时候就需要引用。

  • 对于单个特殊字符,可以使用\来引用,如rm -rf tmp\*.txt
  • 对于大量字符的时候,可以使用单引号,如echo '$(ls)',此时输出的内容就不是ls命令的标准输出,而是$(ls)字符串
  • 当想引用单个字符但是保留变量,可以使用双引号,如echo "list is : $(ls)",输出内容就是list is : test.txt,如果不想引用某个变量,就可以加\,如echo "list is : \$(ls)",输出内容就是list is : $(ls)

函数

定义函数

name(){
command-list
}

执行函数

name

删除定义

unset name

带参数函数

name(){
$1 代表第一个参数
$2 代表第二个参数
$# 代表参数个数
}
name 参数1 参数2

常用工具

find查找文件

find [path] [expression]
  • path参数指定了find所要查找的目录树的起点,可以制定多个目录树作为起点
  • expression可以由若干个表达式构成搜索条件

具体见:https://www.cnblogs.com/soymilk2019/p/11758086.html

当找到后,我们可以使用-exec ls -l { } \来制定找到后所想要执行的命令。

无论find命令看上去多复杂,其本质指定了3个部分:搜索起始目录,一些搜索条件,对于找到文件所做的操作。

which查找命令所在路径

which 命令
whereis 命令

例子:

which ls

输出:
/usr/bin/ls

xargs命令

如果有大量文件需要删除,-exec参数是十分消耗资源的,如果使用$(command)进行rm命令的拼接,有可能参数超出rm命令所能容纳的参数。xargs就派上用场了。

command1 | xargs command2

命令command1的标准输出流经管道作为xargs命令的标准输入当作命令command2的参数执行。如果xargs从标准输入得到大量参数,会智能分步执行。

file命令判断文件类型

file 文件名

dd命令数据备份

dd 能保持文件的原有的格式布局,cp只是针对数据填满一款存储区域,对于一些较大的具有特殊文件,建议使用dd

dd if=[file] of=[file] count=[blocks] bs=[bytes]
  • if告诉dd输入数据
  • of告诉dd输出数据到指定地方
  • count指定数据大小
  • bs指定一次读写的字节数

压缩与解压

https://blog.csdn.net/shengjie87/article/details/106684662

下载

curl和wget

信号

发送信号

我们可以把信号看作是软中断,当有一些重要事件发生的时候,他们就会发送到程序中。如何发送信号呢,kill命令就是专门发送信号的。
信号可以理解为一个进程给另外一个进程发送消息。

处理信号

trap命令可以定义信号的回调处理函数。

trap cmd 信号1 信号2

当其他进程给这个进程发送信号的时候,就会执行cmd命令或者函数。这个有什么用呢?
比如有个命令会产生缓存文件,当命令执行完成后会删除缓存文件,然而有时候这个命令执行到一半被杀了,这时候缓存文件还保留在硬盘中,这样不好。我们可以使用trap命令,当接收到TERM信号后,可以回调rm命令删除缓存。

当一个进程接收到一个信号后,先会查看该信号是否被忽略,如果没有被忽略就执行注册的信号处理函数,如果没有注册就会执行默认行为。

忽略信号

有时候我们不希望进程被杀掉,怎么办,就可以使用忽略信号。
只需要把trap命令中的操作指定为空就可以

trap '' 信号1 信号2

那么此时如果进程接收到了相关信号,就会进行信号忽略。

linux三剑客

基础正则表达式

^(对于每一行以…开头)

例子:
输出以e打头的每一行

[root@VM-101-190-centos ~/dexuantang]# cat test.sh 
echo $0
echo $1
echo $#
echo $@
ls
pwd
[root@VM-101-190-centos ~/dexuantang]# grep "^e.*" test.sh 
echo $0
echo $1
echo $#
echo $@

$(对于每一行以…结尾)

例子:
输出以s结尾的行

[root@VM-101-190-centos ~/dexuantang]# cat test.sh 
echo $0
echo $1
echo $#
echo $@
ls
pwd
[root@VM-101-190-centos ~/dexuantang]# grep ".*s$" test.sh 
ls

^$(空行)

常见作用:排除文件中空行

grep -v "^$" 文件名

.(任意一个字符)

例子:
输出以s包含exxo的行,x代表任意字符

[root@VM-101-190-centos ~/dexuantang]# cat test.sh 
echo $0
echo $1
echo $#
echo $@
ls
pwd
[root@VM-101-190-centos ~/dexuantang]# grep ".*e..o.*" test.sh 
echo $0
echo $1
echo $#
echo $@

*(前一个字符连续出现0或者多次)

.*(任意字符,贪婪匹配)

什么叫贪婪匹配呢,举个例子

grep "^.*t" test.txt

这时候test.txt内容为

jstqdetsssa
jjjjtkkkktooootssss

这时候他会以贪婪模式进行匹配,也就是匹配到了下面内容

jstqdetsssa
jjjjtkkkktooootssss
会尽可能多的匹配内容

.*?(任意字符,非贪婪匹配)

grep "^.*?t" test.txt

这时候test.txt内容为

jstqdetsssa
jjjjtkkkktooootssss

这时候他会以贪婪模式进行匹配,也就是匹配到了下面内容

jstqdetsssa
jjjjtkkkktooootssss
遇到第一个匹配到就会停止

[](方括号内字符或关系)

  • [abc] 匹配a或者b或者c
  • [a-z] 匹配任意小写字母
  • [0-9] 匹配任意数字
  • [a-zA-Z0-9] 匹配任意小写字母或者大写字母或者数字
  • [^ab] 除了a或者b以外的任意字符
  • [a-z|A-Z] 匹配任意小写字母或者大写字母或者|

扩展正则表达式

+ 号,前一个字符出现了1次或者多次以上

grep -E "0+" test.txt

grep只支持基础正则,如果想要进行扩展,只能加-E,
0+代表0出现了1次或者多次以上。

一般与[]擦出不一样的火花
如:

grep -E "[0-9]+" test.txt

匹配出数字

() 被括起来的内容,表示一个整体(一个字符)

例子

grep -E "oldb(o|e)y" test.txt

匹配oldboy或者oldbey

{} 连续出现

o{n,m} 前一个字母o,至少连续出现n次,最多连续出现m次
o{n} 前一个字母o,连续出现n次

?连续出现,前一个字符出现0次或者1次

例子

grep -E "go?d" test.txt

匹配gd或者god

三剑客

命令特点过滤速度最快
grep过滤过滤速度最快
sed替换修改文件内容,取行取出范围内容,修改文件内容
awk取列,统计计算取列,对比,比较

grep

选项含义
-E支持扩展正则
-A-A5 匹配你要的内容并且显示接下来的5行
-B-B5 匹配你要的内容并且显示接上面的5行
-C-C5 匹配你要的内容并且显示接上下5行

sed

特点和格式

功能:找谁干啥,找谁(某一行),干啥(增删改查)
默认不支持扩展正则,如果要加扩展正则,需要加r参数

  • 2p. 指定行号进行查找
  • 1,5p 指定行号范围进行查找
  • /lidao/p 类似grep过滤,//里面可以写正则
  • /10:00/,/11:00/p 范围过滤

例子:

  1. 输出test.txt的第三行
sed -n "3p" test.txt
  1. 输出test.txt的第1-5行
sed -n "1,5p" test.txt
  1. 输出test.txt的第4到最后1行
sed -n "4,$p" test.txt
  1. 输出test.txt的包含 boy或者girl的行
sed -nr "/(boy|girl)/p" test.txt
  1. 输出test.txt的第一个为10:00到最后一个为11:00的行
sed -nr "/10:00/,/11:00/p" test.txt

参数为d,主要功能为删除某一行,如果想要删除某个字符,就需要试用到替换

例子:

  1. 删除test.txt的包含 boy或者girl的行
sed -r "/(boy|girl)/d" test.txt
  1. 删除test.txt的第1-5行
sed "1,5d" test.txt
  1. 删除文件中空行或者包含#号的行
sed -r "^$|#d" test.txt
增加
  • 参数a append追加,向指定行或者每一行追加内容(后一行)
  • 参数i insert插入,向指定行或者每一行插入内容(前一行)
  • 参数c replace替代,替换这一行的内容

例子:

  1. 在test.txt的包含 boy或者girl的行下追加一行字符串test
sed -r "/(boy|girl)/a test" test.txt
  1. 在test.txt的第5行前插入一行字符串test
sed "5i test" test.txt
  1. 替换test.txt的第5行为字符串test
sed "5c test" test.txt
替换

参数为s
一般格式:

s/查找内容正则/替换内容/g

g代表全局替换,sed默认只替换每一行第一个匹配的内容

例子:

  1. 替换test.txt的oldboy单词为test
sed "s/oldboy/test/g" test.txt

后向引用(先保护,再引用)

例子:

  1. 在每一行开头增加 ‘<’ 结尾增加 ‘>’
sed -r "s/(.*)/<\1>/g" test.txt

\1代表获取()中的内容

  1. 替换test.txt的ip为0.0.0.0
sed -r "s/([0-9]{1,3}\.){3}[0-9]{1,3}/0.0.0.0/g" test.txt
  • 3
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值