【系统性学习】Linux Shell易忘重点整理

news2024/11/17 5:56:51

本文主要基于《实用Linux Shell编程》总结,并加入一些网上查询资料和博主自己的推断。
其中命令相关的,已抽取出来在另一篇系统性学习】Linux Shell常用命令中,可以一起使用。

文章目录

    • 一、基础知识
    • 二、命令与环境
    • 三、变量和数组
    • 四、条件流程控制
    • 五、循环
    • 六、函数
    • 七、通配符、正则表达和文本处理
    • 八、进程与作业
    • 九、其他话题
    • 十、Bash调试

一、基础知识

  1. Linux 系统主要目录及简单描述
    在这里插入图片描述
    在这里插入图片描述
目录描述
/binbin 是 Binaries (二进制文件) 的缩写, 这个目录存放着最经常使用的命令
/boot内核及其他系统启动时需要的文件,包括一些连接文件以及镜像文件
/devdev 是 Device(设备) 的缩写, 存放的Linux 的外部设备,Linux把所有外设都看做是一个文件,对文件的操作就是对外部设备的操作
/etcetc 是 Etcetera(等等) 的缩写,用来存放所有的系统管理所需要的配置文件,该目录及子目录下有很多.conf文件
/home用户的主目录,系统默认的普通用户主目录为/home/<acount_name>,如上图中的 alice、bob 和 eve,保存用户自己的配置文件、文档、数据等
/liblib 是 Library(库) 的缩写,存放着系统最基本的动态连接共享库文件(由/bin和/sbin使用),其作用类似于 Windows 里的 DLL 文件。几乎所有的应用程序都需要用到这些共享库。/user/lib中包含更多用于用户程序的库文件
/lost+found这个目录一般情况下是空的,当系统非法关机后,这里就存放了一些文件,用于系统修复和恢复
/mnt系文件系统挂载点,一般用于安装移动介质,其他文件系统的分区、网络共享文件系统或者任何可安装的文件系统。比如可以将光驱挂载在 /mnt/ 上,然后进入该目录就可以查看光驱里的内容了。
/optopt 是 optional(可选) 的缩写,主要由第三方开发者用于安装和卸载他们的软件包。比如你安装一个ORACLE数据库或者spark就可以放到这个目录下。默认是空的。
/procproc 是 Processes(进程) 的缩写,是一种伪文件系统(也即虚拟文件系统),存储的是当前内核运行状态的一系列特殊文件,这个目录是一个虚拟的目录,它是系统内存的映射,我们可以通过直接访问这个目录来获取系统信息(如 /proc/version)。这个目录的内容不在硬盘上而是在内存里,我们也可以直接修改里面的某些文件,比如可以通过下面的命令来屏蔽主机的ping命令,使别人无法ping你的机器:echo 1 > /proc/sys/net/ipv4/icmp_echo_ignore_all
/root该目录为系统管理员,也称作超级权限者的默认主目录。
/sbins就是 Super User 的意思,是 Superuser Binaries (超级用户的二进制文件) 的缩写,这里存放的是超级用户管理系统时使用的系统管理程序。普通用户几乎没有权限执行这里面的命令。/user/sbin是超级用户使用的比较高级的管理程序和系统守护程序
/tmptmp 是 temporary(临时) 的缩写这个目录是用来存放一些临时文件的。当系统重启时,改目录的文件会被自动清空
/usrusr 是 unix shared resources(共享资源) 的缩写,这是一个非常重要的目录,用户的很多应用程序和文件都放在这个目录下,类似于 windows 下的 program files 目录。
/varvar 是 variable(变量) 的缩写,这个目录中存放着在不断扩充着的东西,我们习惯将那些经常被修改的目录放在这个目录下。包括各种日志文件。
  1. ls -l 详情解释:
-rw-------.  1 root root 1.3K Dec 14 01:38 anaconda-ks.cfg
dr-xr-xr-x. 17 root root  224 Dec 14 01:38 bin
  • 第一列共10位,第1位表示文档类型,d表示目录,-表示文件,l表示链接文件,d表示可随机存取的设备,如U盘等,c表示一次性读取设备,如鼠标、键盘等。后9位,依次对应三种身份所拥有的权限,身份顺序为:owner、group、others,权限顺序为:readable、writable、excutable
  • 第二列,对于文件表示硬链接数,表示有多少个文件链接到inode号码。对于目录表示子目录数(包括隐藏文件),所有目录都包含".“和”…"两个隐藏目录,所以目录的第二列>=2
  • 第三列表示拥有者,user
  • 第四列表示所属群组,group
  • 第五列表示文档容量大小
  • 第六列表示文档最后修改时间,注意不是文档的创建时间
  • 第七列表示文档名称。以点(.)开头的是隐藏文档
  1. 账户权限说明:对于文件,读:可以查看 写:可以修改 执行:可以运行。对于目录,读:可以浏览,用ls 写:可以创建和删除文件 执行:可以进入该目录。
  2. SUID:有的可执行二进制文件的账户权限为rws,s是SUID(即set uid),表示其他账户在执行时,有文件所有者的权限。如passwd命令会改/etc/shadow文件,这个文件只有root用户可以修改。但其他账户同样可以执行passwd修改该文件。原因就是passwd文件是s权限。chmod u+s filechmod 4755 file添加该权限。rwS显示S是不正常的,给文件添加x权限才会正常。SUID仅对可执行二进制文件起作用。
  3. SGID:有的可执行二进制文件的所属组权限为rws,,s是SGID(即set gid)表示其他账户在执行时,具有文件所属组的权限。对目录设置SGID,则作用为:任何账户如果可以在该目录内建立新文件或新的子目录,那么新文件和子目录的所属组与该目录的所属组保持一致。SGID属性要保证目录或文件对所属组由x权限,否则为大写S。chmod g+s filechmod 2755 file添加该权限
  4. SBIT:粘滞位,t是SBIT只有目录可以设置,作用是:在一个大家都有权限的目录下,账户不能删除别人的文件或目录。chmod o+t filechmod 1755 file添加该权限。SBIT要求其他账户有执行权限,否则为大写T。

二、命令与环境

  1. linux命令分为内置命令和外部命令:help查看所有内置命令和关键字列表, help command查看内置命令详情。外置命令:which command查看外置命令位置,which无法对内置命令生效。command --help显示外置命令详情。
  2. 内置变量PS1,主命令提示参数。重新登陆shell则恢复。永久保持写入~/.bashrc中。
\h 计算机名
\t 当前时间
\u 账户名
\w 当前路径
> PS1="\h@\u@\t$" #输入
host-10-31-17-80@user_client@16:17:03$ #提示符从>改变了
  1. 搜索路径PATH,路径用:隔开,按顺序先后查找,找到就停止。在原路径后面加路径PATH='$PATH:/tmp/bin'
  2. 要永久改变环境变量,将修改写进~/.bashrc文件中。
  3. 权限掩码umask
  4. source和点命令:souce file. file等价,如果file不在当前目录下,会在$PATH下找。
  5. 直接执行脚本文件和source都能执行脚本中的命令。差异:a. 脚本在子shell中运行,而source是在父shell b. 直接运行脚本需要脚本有x权限,source不需要
  6. 命令解释顺序及改变。命令类型查看用type command
alias->keywords->function->built-in->$PATH
别名->关键字->函数->内置命令->外部命令
  • command <命令> 禁用别名和函数,先处理内置命令和外部命令
  • builtin <命令> 只查找内置命令
  • enable 禁用(-n)和使能内置命令(尽量少用,要避免自己的编写的命令和内置命令重名)
  1. 命令或程序结束后会返回一个退出状态,取值0-255,0表示成功执行。内置变量$?存了上一条命令的退出状态 。
  2. 内置命令true用于返回成功的状态,false则是失败。
  3. 管道左侧|右侧,理解成左侧命令的输出,会给到右侧命令的输入,所以右侧命令不需要写代表输入的参数。
  4. 执行一个shell命令会自动打开标准输入文件(stdin)和标准输出文件(stdout),他们默认对应终端键盘和终端屏幕,分别对应文件描述符0和1。文件描述符(file descriptor,fd)是进程对其打开文件的索引,形式上是个非负整数。
> ls -l /dev/std*
lrwxrwxrwx 1 root root 15 Aug 19  2015 /dev/stderr -> /proc/self/fd/2
lrwxrwxrwx 1 root root 15 Aug 19  2015 /dev/stdin -> /proc/self/fd/0
lrwxrwxrwx 1 root root 15 Aug 19  2015 /dev/stdout -> /proc/self/fd/1
> ls -l /proc/self/fd/*
lrwx------ 1 user_client users 64 Oct 22 17:00 /proc/self/fd/0 -> /dev/pts/0
lrwx------ 1 user_client users 64 Oct 22 17:00 /proc/self/fd/1 -> /dev/pts/0
lrwx------ 1 user_client users 64 Oct 22 17:00 /proc/self/fd/2 -> /dev/pts/0

Linux下的tty和pts详解
概述Linux TTY/PTS的区别
简单的说,/dev/pts/0 可以当做一个终端,这个终端连接了输入和输出,所以fd/0(标准输入)、fd/1(标准输出)、fd/2(标准错误)都可以连到这个终端上来。

  Input  +--------------------------+  R/W   +------+
----------->|             |<---------->| bash |
      |     pts/1      |      +------+
<-----------|             |<---------->| lsof |
  Output  | Foreground process group |  R/W   +------+
      +--------------------------+                
  1. 输入重定向: 命令 输入->命令 < 文件名(不能是带输出的命令)
  2. 输出重定向: 命令(能产生输出)->命令(能产生输出) >文件名命令(能产生输出) >>文件名追加模式。> 文件名可以创建空文件或者清空文件。输出重定向是不安全的。如果想不覆盖源文件,可开启noclobber选项,set -o noclobber
  3. 标准错误输出(stderr),对应fd/2,普通重定向>不起作用。需要 2> 实现重定向。
  4. 同时处理,1>file1 2>file2标准到file1,错误到file2,>file 2>&1同时输出到file(等价 &> file>& file)。
  5. “黑洞”,/dev/null一般用作垃圾箱,把不要的输出重定向到这里,如2> /dev/null
  6. 一行多命令,用;隔开。
  7. 后台执行:command &,执行后会输出 [工作号] 进程号
  8. 续行:命令太长可用\来分行,PS2控制续行提示符。
  9. 特殊文件名处理:空格前面加\,-a.txt这样-开头的,用vi -- -a.txtvi ./-a.txt。因为-后面会被认为是选项。Bash规定--(空格)后面的东西不是选项,而是文件名或参数。
  10. 小括号,大括号,中括号

三、变量和数组

  1. Bash只有字符串类型。整数型字符串赋值被变量时,变量相当于多了个整数属性,可以进行整数运算。
  2. 变量定义时,等号左右两边不能有空格。引用变量时,前面加$
  3. 双引号作用,保留空格。a= b=" ",a是为空的,b才能保留空格。
  • 单引号:相当于raw字符串:被单引号括起的内容不管是常量还是变量者不会发生替换。
  • 双引号:把双引号内的内容输出出来;如果内容中有命令、变量等,会先把变量、命令解析出结果,发生替换,然后在输出最终内容来。
  • 不加引号:不会将含有空格的字符串视为一个整体输出, 如果内容中有命令、变量等,会先把变量、命令解析出结果,然后在输出最终内容来,如果字符串中带有空格等特殊字符,则不能完整的输出,需要改加双引号,一般连续的字符串,数字,路径等可以用。
  1. 取命令执行结果:`命令`,$(命令)都可以取命令输出的结果。要保留换行符、首尾空格等符号,则用"$(命令)"。可以把()当做子shell,里面的操作不会对父shell产生影响。少用反引号,因为$()便于嵌套。注意对比取变量${变量}和取命令输出结果$(命令)
# 测试父shell中变量
> x=10
> b=$(echo $x)
> echo b=$b x=$10
b=10 x=0
> b=$(x=5;echo $x)
> echo b=$b x=$x
b=5 x=10 --父shell中的x没被改变

# 测试嵌套
> time=$(echo Today is $(date))
> echo $time
Today is Sun Oct 23 14:06:37 CST 2022

# 取变量和取命令
> aa=${date}
> echo aa
  --空,因为变量date没有定义
  
# 测试定义命令同名变量,不会影响命令执行
> date=3 #同名变量
> t1=$(date)
> t2=$date
> t3=${date}
>  echo -e "t1=$t1\nt2=$t2\nt3=$t3"
t1=Sun Oct 23 14:11:21 CST 2022
t2=3
t3=3

# 反斜杠取消符号原有功能
> echo "`date`"
Sun Oct 23 14:19:05 CST 2022
> echo "\`date\`"
`date`
> echo "$(date)"
Sun Oct 23 14:19:22 CST 2022
> echo "\$(date)"
$(date)
  1. 整型计算:放在双括号间或let后面。$((表达式))可取出表达式计算结果。单独的((表达式))仅仅是计算,而没有输出。i++(先用后加),++i先加后用,支持+=,-=,*=,/=,%=,^=等运算。支持算木运算((条件?结果1:结果2))$(())可替换成$[],注意,有$时才能替换。另外,declare -i var定义了整型变量后,var=表达式不需要括号也可进行整型计算。
# 命令行理解
w=date
> echo $w
date
> $w  #直接被执行
Sun Oct 23 16:03:32 CST 2022

# 表达式结果
> echo $((50/20))
2
> echo $((w=50/20))
2
> echo $w
2
> echo $[a=10+5]
15
> echo $a
15

# 整型变量
>declare -i v
>v=$a+$w
>echo $v
30
>v=a+10 # 甚至不需要引用
>echo $v
25
  1. 浮点运算:用bc或者awk。echo "scale=5;表达式|bc"或者直接bc开客户端运算,quit退出。
  2. 其他进制:bash支持其他进制运算,只要在算数表达式能生效的地方都可以使用。两种书写方法,a. 基数#数值,基数可取2到64。b. 0开头表示8进制,0x开头表示十六进制:
((w=8#16)) #8进制的16赋值给w
((w=016))  #等价
((w=16#25)) #16进制的25赋值给w
((w=0x25))  #等价
  1. 数组:bash只支持一维数组,下标默认从0开始。单独引用数组名时,返回数组第一个元素。打印数组全部详细信息,用 declare -p 数组名
# 定义
y=(aa bb cc)
y=([1]=aa [3]=bb [5]=cc) # 非连续下标定义
>echo $y
aa
> declare -p y
declare -a y='([0]="aa" [1]="bb" [2]="cc")'

# 引用,${数组名[下标]}
echo $y  # 打印数组第一个元素
echo ${y[1]}
echo ${y[*]} #得到数组所有元素,作为一个整体
echo ${y[@]} #得到数组所有元素,作为一个个个体
echo ${#y[*]} #得到数组个数
echo ${!y[*]} #得到数组所有下标
# 增加或修改元素
y[3]=dd
y[2]=cc2
# 删除元素或数组
unset y[1]
unset y
  1. 关联数组(其他语言里的map):Bash4以上版本才支持。使用和数组类似,定义如下:
declare -A age=([Mike]=12 [Jack]=24 [Tom]=30)
# 显示详情
declare -p age

# 取建
echo ${!age[@]}
# 取值
echo ${age[@]}
  1. Bash中的特殊变量。P118
变量含义
$0脚本自身的名字,或者shell的名字
$N脚本或函数的位置参数,$1,$2,...${10},注意大于9要用{}包起来
$#位置参数个数,不包括$0
$*所有位置参数(整体作为一个字符串),不包括$0
$@所有位置参数(每个作为独立字符串),不包括$0
$?上一条命令退出状态
$$当前shell进程ID
$!最后一个命令的进程ID
$-当前shell的选项,若echo $- 的输出中包含i,则表示是交互式shell,包含C则表示noclobber开启
$_上条命令的最后一个参数
  1. set --清除所有位置参数,不包括$0
  2. 父shell与子shell及其进程ID。
  3. 一些常用内置变量(或者说环境变量)P121
变量含义
BASHbash的完整路径,默认为/bin/bash
BASH_ENV非交互式分登陆模式中(比如执行shell脚本时),先执行一遍该变量下指定的脚本
CDPATH命令cd的搜索路径,多个路径用:隔开,用于减少输入全路径的情况
DISTACK当前目录栈存放的数组,配合poshd,popd,dirs使用
FUNCNAME当某函数被调用时,该变量为函数名;实际上它是数组,记录调用链上所有的函数名
GLOBIGNORE要忽略的通配模式列表,冒号分割,定义了文件名扩展时(通配符模式下)要忽略的文件名集合,本身也支持通配符,例如GLOBIGNORE=a*;b*会使得ls *忽略所有a和b开头的文件
HISTFILE存放命令历史的文件,通常为~/.bash_history
HISTFILESIZE命令历史文件保存的最大行数
HISTIGNORE不需保存的历史命令序列,多个通配符模式列表组成,由冒号分隔。用冒号隔开。如HISTIGNORE=ls:t*:\&,将忽略ls命令,和t开头的命令,并且&表示连续输入的相同命令只被记录一次,赋值时需要用\屏蔽其将命令后台挂起含义
HOME用户主目录,通常为/home/用户名,不要改,会影响cdcd ~的结果
LINENO脚本中当前行号
OLDPWD前一个工作目录,cd -等价于cd $OLDPWD
OPTARG存放getopts参数的值
OPTIND待处理的下一个getopts参数索引,初始值为1
PATH外部命令搜索路径,多个以冒号隔开
PPID父进程(父shell)的进程ID
PWD当前工作目录
RANDOM0-32767之间一个随机数
REPLYread不加变量时,变量缓存。select 用户选择项缓存
SECONDS当前shell的启动时间
SHELL登陆linux后的默认shell,/bin/bash比较常用
SHELLOPTSshell的选项,冒号隔开,例:braceexpand:emacs:hashall:histexpand:history:interactive-comments:monitor
SHLVL第一次打开一个shell终端,值为1,没进入一层子shell,值增加1
TMOUT如果该值大于0,当前shell在等待TMOUT秒后没有任何输入就会自动退出
BASH_SOURCE更稳健地获取自身脚本路径。BASH_SOURCE是数组,不过它的第一个元素是当前脚本的名称。这在source的时候非常有用,因为在被source的脚本中,$0是父脚本的名称,而不是被source的脚本名称。而BASH_SOURCE就可以派上用场了。还可和FUNAME配合打印哪个脚本调用了哪个函数。
BASH_SUBSHELL检查当前环境是不是在subshell中,这个值在非subshell中是0;每进入一层subshell就加1
  1. 常用变量赋值表达式。下面的Default可以是变量,取$变量。var也可以是0(不能赋值)或者位置变量1,2,3…10(不能赋值)。
表达式含义
${var:-Default}若var未定义或为空值,则表达式的值为Default,var不变
${var:=Default}若var未定义或为空值,则表达式的值为Default,var赋值Default
${var:?Message}若var未定义或为空值,则打印Message且后续代码不再执行,var不变。
${!pre*}匹配之前所有声明的以pre开头的变量
${!pre@}匹配之前所有声明的以pre开头的变量
  1. 常用内置字符串操作(支持通配符)。sed和awk也有字符串处理函数,但内置操作最快。下表中的str可替换成数组名[*],则表达式对于数组每个元素做处理。expr命令也可处理字符串,支持正则表达式。
表达式含义
${#str}字符串str的长度
${str:pos}从str的pos位置提取子串,到结尾
${str:pos:len}从str的pos位置提取长度为len的子串
${str#glob}从str的开头,删除最短匹配的通配符模式glob
${str##glob}从str的开头,删除最长匹配的通配符模式glob
${str%glob}从str的结尾,删除最短匹配的通配符模式glob
${str%%glob}从str的结尾,删除最长匹配的通配符模式glob
${str/glob/replacement}用replacement代替第一个glob,最长匹配
${str//glob/replacement}用replacement代替所有glob,最长匹配。
${str/#glob/replacement}用replacement代替第一个包含开头的glob,最长匹配
${str/%glob/replacement}用replacement代替第一个包含开头的glob,最长匹配
> a=(one on1 tow)
> echo ${a[*]#o*}
ne n1 tow
> echo ${a[*]##o*}
tow
> b=${a[*]##o.*}
>  declare -p b
declare -- b="one on1 tow"
> echo ${a[@]##o*}
tow
> c=${a[@]##o*}
> declare -p c
declare -- c="tow"

四、条件流程控制

  1. 条件判断命令:test 条件表达式[ 条件表达式 ],中括号前后一定要有空格。$?取命令退出结果来看条件是否满足。满足则退出结果为0,否则为1。
  2. 整型关系运算:
条件表达式含义
[ int1 -lt int2 ]int1小于int2
[ int1 -le int2 ]int1小于等于int2
[ int1 -gt int2 ]int1大于int2
[ int1 -ge int2 ]int1大于等于int2
[ int1 -eq int2 ]int1等于int2
[ int1 -ne int2] int1不等于int2
  1. 字符串关系运算,注意需要加\转义,且str最好用""保护首尾的空格。
条件表达式含义
[ str1 == str2 ]str1等于str2,也可以用str1=str2
[ str1 != str2 ]str1不等于str2
[ str1 > str2 ]字典序,str1大于str2,str1在str2后面
[ str1 < str2 ]字典序,str1小于str2,str1在str2前面
[ -z str ]str为空串zero,长度为0
[ -n str ]str非空not-zero,长度大于0
[ str ]同上
[[ str =~ regex ]]str匹配正则表达式regex,注意=~只能在中括号中使用,相当于启用正则匹配
  1. 文件属性判断,
条件表达式含义
[ -a file ]file存在
[ -e file ]file存在,同a
[ -s file ]file存在且非空(字节数大于0)
[ -d file ]file存在且是一个目录
[ -f file]file存在且是一个普通文件
[ -h file]file存在且是一个符号链接
[ -L file]file存在且是一个符号链接,同h
[ -p file]file存在且为已命名管道
[ -u file ]file存在且设置了SUID
[ -g file ]file存在且设置了SGID
[ -k file ]file存在且设置了粘滞位
[ -r file ]file存在且当前用户有读权限
[ -w file ]file存在且当前用户有写权限
[ -x file ]file存在且当前用户有执行权限,如果是目录,则有进入该目录权限
[ -N file ]file存在且最后一次读取后有更改
[ -O file ]file存在且当前用户是该文件所有者
[ -N file ]file存在且当前用户所属组是该文件所属组
[ -t FD]文件描述符打开,并指向一个终端
[ f1 -nt f2 ]f1修改时间比f2新newer than,或f1存在且f2不存在
[ f1 -ot f2 ]f1修改时间比f2旧older than,或f2存在且f1不存在
[ f1 -ef f2 ]f1和f2有相同的设备和节点号(互为硬链接)
  1. 逻辑与:[ 条件表达式1 -a 条件表达式2 ],逻辑或:[ 条件表达式1 -o 条件表达式2 ],逻辑非:[ ! 条件表达式 ]。test同样。优先级:非、与、或,多条件可用(),括号最优先。
  2. 双中括号代替test或[].[[]]使得P146:
  • a. (,<等不用加反斜杠;
  • b. 保留字符串首尾有空格时,也不需要加双引号
  • c. 判断字符串相等或者不等时,右侧支持通配模式。*代表0或多个字符,?代表一个字符
  • d. 支持&&|| 表达 代替 -a ,-o
  1. 双小括号助力整数条件运算。(())使用场景:
    I. 计算表达式,((表达式))等价于 let 表达式 。表达式结果不是逻辑0或1的时候,该表达式不报错的退出状态永远是0。
    II. 上述表达式可以是整数相关的条件表达式,使得
    a. (,<等不用加反斜杠;
    b. >,<,!=可应用于整数,并且>=,<=,==也可使用
    c. 支持&&|| 表达 代替 -a ,-o

  2. 命令的与或非:
    I. 与:命令1 && 命令2 ,命令结果都为0,才为0。若命令1结果为非0,则命令2不再执行。可用来实现命令依赖。
    II. 或:命令1 || 命令2 ,命令结果有一个为0,则为0。若命令1结果为0,则命令2不再执行。可用来按优先级至少执行一个命令。
    III. 非: ! 命令1 ,命令结果有一个为0,则为0。若命令1结果为0,则命令2不再执行。可用来按优先级至少执行一个命令。

# 样例
>[-r a.txt -a -w b.txt ] #判断文件存在和权限
>echo $?
0

# 优先级
> x=5;y=10;z=20
>[ \($x -eq 5 -o $y -gt 5\) -a $z -lt 5 ]
> echo $?
0
# 双中括号
>[[ ($x -eq 5 || $y -gt 5) && $z -lt 5 ]]
> echo $?
0
# 双小括号
>(( ($x == 5 || $y > 5) && $z < 5 ))
> echo $?
0

# 双中括号字符串相等或不相等右侧通配模式
>[[ $s1 == a* && $s2 != b? ]]

# 命令与或非
> [ 1 -eq 2 ] && [ 1 -lt 3 ] 
> echo $?
1
  1. 判断变量是否有定义:[-v 变量名]test -v 变量名。结果为0则表示有定义。或者set,从结果中找,存在则表示有定义,但这种方式太繁琐。
    10.if控制结构,可嵌套使用。
# if命令
if 命令 #该命令的退出结果为0,则执行then后面的语句
then
	命令1
	命令2
	...
if

if 命令;then 命令1;命令2...;fi  # 单行模式

#if-else 命令
if 命令
then 
	命令(命令组)
else #可以没有
	命令(命令组)
fi

if 命令;then 命令(命令组);else 命令(命令组);fi

#if-elif 命令
if 命令1
then 
	命令(命令组)
elif 命令2
then 
	命令(命令组)
elif 命令3
then 
	命令(命令组)
else  #可以没有
	命令(命令组)
fi
# 命令中的重定向
if cp a.txt b.txt 2>/dev/null #重定向不影响命令退出状态
then
 	echo “copy done”
fi

# if-else的替换
if cmd1; then cmd2;else cmd3;fi
cmd1 && cmd2 ||cmd3 # 等价
  1. case 控制结构,如下模式可以是1个,或者多个,多个用|分割,或关系。模式支持正则表达式。如[6-7][0-9]表示60~79。
case $变量 in
	模式1)
		命令(命令组);;
	模式2)
		命令(命令组);;
	...
	*) #表示其他情况
		命令(命令组);;
esac
# 样例
case $score in
	100)
		echo "Full Mark";;
	9[0-9])
		echo "Excellent";;
	8[0-5] | 8[6-9])
		echo "Very Good";;
	[6-7][0-9])
		echo "Passing";;\
	*)
		echo "Failed,or Error";;
esac
  1. exit的退出状态默认为前一条命令的退出状态。也可以exit N带整型参数,则退出状态为N,这个特点可以配合if(产生exti不同结果)和case(对不同结果做处理)命令使用。
  2. here文档和case可模拟select命令的功能。详见常用命令here。
# 结合case使用,模拟select命令
cat << INPUT
choose your role
A)student
B) teacher
INPUT

read var
case $var in
	A)
		...;;
	B) 
	 	...;;
	*)
		echo "error";;
esac

五、循环

  1. for控制流程,如下“”列表“”可以是字符串字面量,字符串变量,或位置参数枚举$*,$@,或数组枚举${数组名[*]${数组名[@]
    I. 为字符串时,元素分割符由IFS指定(Internal Filed Seperator,字段分割符),默认为“空白字符”,linux中的"空白字符"包括:空格、\t、换行\n、回车\r\n\r 是不同的:\r是指 在同一行中, 使光标回到该行的行首。\n是指 光标转到下一行)。IFS使用后要记得恢复。
    II. $*,$@的表现受双引号限制,有引号时"$*"仍是一个整体,"$@"则各元素分别作为一个整体;没有引号时,$*,$@表现一样,每个元素都分别作为一个整体。
    III. ${数组名[*]${数组名[@]同上。
    IV. [in 列表]部分不是必须的,没有的时候相当于 for 变量 in "#@"
for 变量 [in 列表]
do
	命令(命令组)
done
#  单行
for 变量 [in 列表];do 命令(命令组);done


# IFS注意点
> OLD_IFS="$IFS"
> IFS="$OLD_IFS" #用完后要恢复



# IFS 测试
> for a in 1 2 3;do echo  "${a}T";done
1T
2T
3T  --不带引号的字符串,触发天然分割,但该分割不是由IFS指定。
> for a in "1 2 3";do echo  "${a}T";done
1 2 3T  --不触发天然分割和IFS分割
> str2="1 2 3"
> for a in $str2;do echo  "${a}T";done
1T
2T
3T --变量引用触发IFS分割,当前分割符为默认的空白字符
>IFS=":"
> for a in "1:2:3";do echo "${a}T";done
1:2:3T
> str="1:2:3"
> for a in $str;do echo  "${a}T";done
1T
2T
3T  --变量引用触发IFS分割,当前分割符为:
> for a in 1 2 3;do echo  "${a}T";done
1T
2T
3T  --触发天然分割未受影响
> echo $str
1 2 3 --此时,echo得到的str结果可以看出,IFS分割已触发,分割后的元素用空格连接打印
> for a in $str2;do echo  "${a}T";done
1 2 3T --分割符已变,所以即使触发IFS分割,也分割不了
> a=$str
> declare -p str
declare -- str="1:2:3"
> declare -p a
declare -- a="1:2:3"
> echo "1:2"
1:2



所以,可以猜测,IFS只作用于引用变量的时候,即变量引用触发IFS分割,并将变量以IFS字符分割。
in后面只看有多少被分割元素,不触发分割。

# 引号下不同表现
>cat test.sh
for a in "$@";do echo $a;done

>test.sh A B C
A
B
C
>cat test.sh
for a in "$*";do echo $a;done
>test.sh A B C
A B C
>若不加双引号, 即 for a in $*$@,结果都如下
>test.sh A B C
A
B
C  --可理解成,$*也触发天然分割,被切开了

# for 常用大括号扩展
for i in {1..10} # 或{a..z}, a{b,c}k,{10..1}等
do 
	...
done
  1. 算数for循环,三个表达式不是必须的,但;需要保留。循环条件为空时,表示无限循环。
for ((变量初始化;循环条件;变量值更新))
do
	命令(命令组)
done

# 样例1
for ((i=0;i<10;i++));do echo $i;done
# 样例2
i=0
for ((;i<10;));do echo $i;((i++));done
  1. while循环。先判断while后面命令的退出状态,为0时,do后面的命令再执行。
while 命令
do
	命令(命令组)
done
  1. until循环。先判断while后面命令的退出状态,为0时,do后面的命令再停止。
until 命令 #等价于 while !命令
do
	命令(命令组)
done
  1. break和continue可以跳出循环,包括for、while、until。break Ncontinue N跳出N层循环。技巧if 命令;then break/continue;fi可写成命令 && break/continue
  2. 循环的重定向以及和管道的配合。循环结构for、while、until都是以done结尾的,done后面可以接<>做输入输出重定向,或者接| 命令做管道。因为while和until后面是命令,所以命令就有可能需要有输入,那么也是可以在前面加管道的,即 命令 | while 需要输入的命令
# 输出管道,脚本:
for i in c b a m p
do
	echo $i
done | sort # 则该脚本可以输出排序后的值

# 输入重定向:
while read line
do
	echo $line
done < test.txt 

# 输入管道:
cat test.txt|while read line
do
	echo $line
done 

# 输入和输出:
cat test.txt|while read line
do
	echo $line
done > out.txt 

六、函数

  1. 函数定义有三种形式,可接受位置参数,调用时用法和脚本一样
function 函数名
{
	命令(命令组)
}

函数名()
{
	命令(命令组)
}

function 函数名()
{
	命令(命令组)
}
# 一行形式,右大括号前必须要有一个分号
function 函数名 {命令(命令组);}

# 使用
函数名 arg1 arg2 arg3 #函数体力如果有echo,就打印echo内容

# 调用
source 函数定义脚本
$(函数名)
$(函数名 arg1 agr2)
  1. 函数内变量,如果和全局变量同名,则为全局变量,否则需要加上 local 或者declare声明成局部变量;如果是非同名变量,则为局部变量,加上declare -g 则可声明成全局变量。
  2. 当前函数名,存在内部变量FUNNAME中。FUNNAME是一个数组,第一个元素为当前函数名,第二个元素为上一层调用函数名,declare - p FUNNAMEecho ${FUNAME[*]}查看调用链。
  3. 函数的导出与清除。declare -fx fun1, 导出函数,等同 export -f fun1。清除 unset -f 函数名unset 函数名declare -f fun1查看函数定义。
  4. 函数返回命令return, 可带参数N。执行return后,函数中后续命令不再执行。return不带参数时,函数的返回状态为return上一条命令的状态。retrun N时,,函数的返回状态为N。可当做默认函数结尾有个隐含的return。
  5. 递归函数,可以实现,但运行效率较低,且占用系统资源较多,不提倡写递归函数。

七、通配符、正则表达和文本处理

  1. 通配符模式,glob(也叫wildcard)。支持以下几种
通配符含义
*表示任意字符
?表示一个字符
[]范围替换[abc]表示a或b或c,[0-9],[a-z]前面的字符不能大于后面的字符。[A-Z0-9]组合在一起也可以。
[!]不在范围内,[!abc]表示不为a或b或c,[!0-9]表示不为0-9
  1. 扩展通配模式,可通过shopt -s extglob打开扩展(-u 表示关闭),支持:
通配模式含义
*(pattern)匹配所给模式零次或多次,如*(m),表示0个或多个m
?(pattern)匹配所给模式零次或一次
+(pattern)匹配所给模式一次或多次
@(pattern)匹配所给模式仅一次
!(pattern)不匹配所给模式
  1. 通配符模式使用场景
    I. shell命令行里,加单引号,双引号或反斜杠时,失去通配符能力。如ls "*"找的就是名为*的文件。
    II. find -name file,中file支持通配符,且本身就放在双引号或单引号中,如find -name "a*.txt",通配符能力不失去,加反斜杠才失去通配能力。
    III. 条件判断双中括号[[]]的等号或不等号右边支持通配符,右边如果带双引号或单引号或反斜杠,通配符失效。
    IV. 第三章15节的常用内置字符串操作(支持通配符)。如果带双引号或单引号或反斜杠,通配符失效。
# 条件判断中
> [[ "ads" == a* ]]
> echo $?
0
> [[ "ads" == "a*" ]]
> > echo $?
1 --双引号,通配符失效
# 内置字符串操作中
> str="abcd"
> echo ${str/a*/K}
K
> echo ${str/"a*"/K}
abcd  --双引号,通配符失效
  1. GLOBIGNORE,被忽略的通配模式,用冒号分割。仅作用于命令行。
> touch a.txt b.txt c.txt d.txt
> find -name "*"
.
./c.txt
./a.txt
./d.txt
./b.txt
> ls *
a.txt  b.txt  c.txt  d.txt
> GLOBIGNORE=a*:b*
> ls *
c.txt  d.txt
> find -name "*"
.
./c.txt
./a.txt
./d.txt
./b.txt
  1. 正则表达式,各语言的正则表达式支持范围略有不同,具体可查阅【中文,英文】。linux中,平常的正则表达式简称BRE(Basic Regular Expressions),扩展的正则表达式叫ERE(Extended Regular Expressions)。Linux里的正则表达式都是贪婪的(当可匹配多个时,都匹配最长)。常用的正则模式有(其中,"扩展"在egrep命令中可使用):
字符模式含义
.匹配任何单个字符
*匹配零次或多次
?匹配零次或一次(扩展)
+匹配一次或多次(扩展)
\{N\}匹配N次(扩展用{N}
\{N,\}匹配N次或更多次(扩展用{N,}
\{N,M\}匹配至少N次之多M次(扩展用{N,M}
a|b|c匹配a或b或c(扩展)
( )分组符号,如r(able|dress)匹配rable或rdress(扩展)
[x-y]范围,如[0-9]匹配数字
[ ]匹配一组字符中的一个,如[abc]匹配a或b或c
^匹配行首
$匹配行尾
[^]匹配取反,[^0-9]表示非数字,[^abc]表示非a,b,c
\b单词定界符,包含词首和词尾定界符
\<词首定界符
\>词尾定界符
\w等价 [A-Za-z0-9]
\W\w取反,等价 [^A-Za-z0-9]
  1. POSIX字符类。指定匹配字符范围的另一种方法。grep 中和egrep中使用方法一样。tr命令后也可使用单中括号tr [:punct:] X,但为了保持一致,建议都用双中括号。作用:有些字符类比正则表达简单,有些命令只支持POSIX不支持正则(如tr)。
字符类含义
[[:alnum:]]字符和数字,等同于[A-Za-z0-9]
[[:punct:]]标点符号
[[:cntrl:]]控制字符
[[:space:]]空白字符,空格、制表符、竖向制表符、换行、回车等
[[:alpha:]]字母,等同[A-Za-z]
[[:blank:]]空格户制表符Tab
[[:digit:]]所有数字,等同[0-9]
[[:lower:]]所有小写字母,等同[a-z]
[[:upper:]]所有大写字母,等同[A-Z]
[[:xdigit:]]所有 16 进位制的数字
# 样例
grep [[:punct:]] t.txt #过滤出包含空白字符的所有行

八、进程与作业

  1. 挂起进程<Ctrl+Z>,比如进入vi后,在命令模式下,按<Ctrl+Z>挂起进程。jobs查看作业状态。
> vi test.txt # 按<Ctrl+Z>
[1]+  Stopped                 vi test.txt
> jobs
[1]+  Stopped                 vi test.txt

九、其他话题

  1. 目录栈。通常,目录只保留了OLDPWD和PWD,无法再追踪更早之前的记录。pushd、popd,dirs提供了这方面的能力。使用pushd命令记录的目录栈保存在内置变量DIRSTACK中。
pushd cd到目录,并将目录放入目录栈
+/-N 目录栈的“环滑动”,+N从栈顶的第N个项目滑为栈顶,-N从栈底的第N个目录滑为栈顶

>pwd
/usr
> dirs -c
> pushd /usr/bin 
/usr/bin /usr  --永远把当前目录放在栈底
> pushd /var/lib
/var/lib /usr/bin /usr
> declare -p DIRSTACK 
declare -a DIRSTACK='([0]="/var/lib" [1]="/usr/bin" [2]="/usr")'

dirs
-p 每行显示目录栈内一个目录
-v p的基础上带编号,编号大的在栈底
+/-N 不改变目录栈的内容,+N表示从栈顶数第N个目录,-N表示从栈底数第N个目录
> dirs
/var/lib /usr/bin /usr
> dirs -v
 0  /var/lib
 1  /usr/bin
 2  /usr
> dirs -p
/var/lib
/usr/bin
/usr
> dirs +1
/usr/bin

popd 移除栈顶目录,并cd到新栈顶目录
+/-N 
> popd
/usr/bin /usr
> pwd
/usr/bin
> dirs -v
 0  /usr/bin
 1  /usr

## 环滑动
> dirs -v
 0  /opt
 1  /usr/lib
 2  /usr/bin  --从栈顶第2位
 3  /usr
> pushd +2
/usr/bin /usr /opt /usr/lib
> dirs -v
 0  /usr/bin  --原从栈顶第2位
 1  /usr
 2  /opt   --原栈顶滑下来了
 3  /usr/lib
  1. 波浪号扩展
命令含义
cd ~等价cd $HOME
cd ~username到username的home
~+等价PWD,cd ~+
~-等价OLDPWD,cd ~-
~+N~N等价dirs +N
~-N等价dirs -N
  1. 交互式shell和非交互式shell、登录shell和非登录shell
  2. expand_aliases别名功能,交互式shell默认打开,非交互式shell默认关闭。
    I. 不要在脚本内使用别名,不然要显示打开expand_aliases。
    II. 别名不能export,要想在其他shell中使用,将别名放到脚本里,再source 脚本名。
    III. 函数内定义的别名,在函数调用前不能使用。
    IV. 综上,不要在脚本和函数内使用别名。
  3. 并行处理。常用名命令grep,wc,awk和sed等都是单线程的,只能使用一个cpu。服务器有多个cpu时,可以利用GNU的parallel命令,把负载分配到各个cpu上。
    I. parrallel命令通常需要下载安装,官网。
    II. 使用说明。
mpstat # 查看cpu信息,该命令不是所有bash都有
> cat /proc/cpuinfo |grep processor | wc -l # 获取cpu数
2

十、Bash调试

  1. 正式运行脚本前,先set -n set -o noexce,读命令,解释但不执行,用来检查脚本语法
  2. set -uset -o nounset,有变量未定义时提示错误信息
  3. shopt -s shift_verbose,shift移动数大于参数个数时,提示错误
  4. set -vset -o verbose,为调试打开verbose模式,脚本运行时显示读入的每行命令,并原样打印
  5. set -xset -o xtrace,为调试打开echo模式,脚本运行时显示变量替换后的每行命令和参数。只调试一段代码时,在代码前后添加:
set -xv
待调试代码段
set +xv
  1. set -x的提示符为PS4,默认为+,可修改成PS4=+'$[LINENO]'打印代码行号。
  2. bash -x 脚本set -x是一样的,相当于在脚本前增加了set -x。便于脚本测试。
  3. 利用trap捕获信号来调试
  4. 打印内容调试
  5. 利用BASH_SOURCE,BASH_SUBSHELL,FUNNAME等内置变量。
  6. 输出重定向获取log文件来分析
  7. 在代码中增加“调试块”,if语句开控制变量调试信息是否打印
if [$DEBUG = YES];then
	打印调试信息
fi
# 当前执行脚本的绝对路径,可以采用以下方式:
DIR_T="$( cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"

# 在tmp文件夹下创建脚本test.sh 和a.sh
> cat test.sh
echo BASH_SOURCE=${BASH_SOURCE[0]}
echo \$0=$0
DIR_T="$( cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
echo ${DIR_T}
> cat a.sh
echo "This is a.sh"
source test.sh

# 运行
> ./test.sh
BASH_SOURCE=./test.sh --相对路径
$0=./test.sh --相对路径
/opt/user/tmp --绝对路径
> bash test.sh
BASH_SOURCE=test.sh
$0=test.sh
/opt/user/tmp
> ../tmp/test.sh
BASH_SOURCE=../tmp/test.sh --相对路径
$0=../tmp/test.sh --相对路径
/opt/user/tmp
> bash ../tmp/test.sh
BASH_SOURCE=../tmp/test.sh
$0=../tmp/test.sh
/opt/user/tmp
> ./a.sh
This is a.sh
BASH_SOURCE=test.sh
$0=./a.sh  --父脚本的名字
/opt/user/tmp

# BASH_SUBSHELL
> echo $BASH_SUBSHELL
0
> (echo $BASH_SUBSHELL)
1
> ( ( ( ( (echo $BASH_SUBSHELL) ) ) ) )
5
> bash
> echo $SHLVL
1
> echo $BASH_SUBSHELL
0

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/55536.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Linux多线程C++版(八) 线程同步方式-----条件变量

目录1.条件变量基本概念2.条件变量创建和销毁3.条件变量等待操作4.条件变量通知(唤醒)操作5.代码了解线程同步6.线程的状态转换7.代码改进--从一对一到一对多1.条件变量基本概念 互斥锁的缺点是它只有两种状态&#xff1a;锁定和非锁定条件变量通过允许线程阻塞和等待另一个线…

Kamiya丨Kamiya艾美捷抗FLAG多克隆说明书

Kamiya艾美捷抗FLAG多克隆化学性质&#xff1a; 程序&#xff1a;用FLAG肽免疫家兔与KLH偶联。多次免疫后在弗氏佐剂中收集血清使用固定在固相上的肽。 规范&#xff1a; 使用氨基末端分析抗体Met FLAG BAP、氨基末端FLAG-BAP和羧基末端FLAG-BAP融合蛋白和Invitrogen Posite…

跳槽,从这一个坑,跳进另外一个坑

软件测试员跳槽有一个奇怪的现象&#xff1a;那些跳槽的测试员们&#xff0c;总是从一个坑&#xff0c;跳进另一个坑中&#xff0c;无论怎么折腾&#xff0c;也没能拿到更好的offer&#xff0c;更别说&#xff0c;薪资实现爆炸式增长&#xff0c;自身价值得到升华~ 在如今经验…

【Web安全】注入攻击

目录 前言 1、注入攻击 1.1 SQL注入 1.2 数据库攻击技巧 1.2.1 常见的攻击技巧 1.2.2 命令执行 1.2.3 攻击存储过程 1.2.4 编码问题 1.2.5 SQL Column Truncation 1.3 正确防御SQL注入 1.4 其他注入攻击 1.4.1 XML注入 1.4.2 代码注入 1.4.3 CRLF注入 前言 年…

Kotlin高仿微信-第53篇-添加好友

Kotlin高仿微信-项目实践58篇详细讲解了各个功能点&#xff0c;包括&#xff1a;注册、登录、主页、单聊(文本、表情、语音、图片、小视频、视频通话、语音通话、红包、转账)、群聊、个人信息、朋友圈、支付服务、扫一扫、搜索好友、添加好友、开通VIP等众多功能。 Kotlin高仿…

数商云SRM系统询比价有何优势?供应商平台助力汽车零部件企业快速查找供应商

随着中国汽车行业的高速发展、汽车保有量的增加以及汽车零部件市场的扩大&#xff0c;我国汽车零部件行业得到了迅速发展&#xff0c;增长速度整体高于我国整车行业。数据显示&#xff0c;我国汽车零部件的销售收入从2016年3.46万亿元增长至2020年的4.57万亿元&#xff0c;年均…

世界杯——手动为梅西标名

梅西的铁粉来集赞啦。 今天带来了一个为图片添加字样的小功能&#xff0c;我们的测试目标图片是&#xff1a; 我们的测试目标是&#xff1a; 我们使用的是Python语言&#xff0c;使用了Image包用作图片处理&#xff0c;matplotlib包用作坐标查阅&#xff0c;这个坐标还是很好看…

微服务框架 SpringCloud微服务架构 8 Gateway 网关 8.5 全局过滤器

微服务框架 【SpringCloudRabbitMQDockerRedis搜索分布式&#xff0c;系统详解springcloud微服务技术栈课程|黑马程序员Java微服务】 SpringCloud微服务架构 文章目录微服务框架SpringCloud微服务架构8 Gateway 网关8.5 全局过滤器8.5.1 全局过滤器 GlobalFilter8.5.2 案例8.…

segmentation

(用于医学图像分割的金字塔医学transformer) Pyramid Medical Transformer for Medical Image Segmentation 基于CNN的模型通过低效地堆叠卷积层来捕获长期依赖性&#xff0c;但基于注意力的模型明确地构建了所有范围的关系。然而&#xff0c;为全局关系分配可学习参数是昂贵…

WebAPI项目搭建及其发布测试

目录 1.创建项目 2.配置 3.发布 4.测试页面 1.创建项目 &#xff08;1&#xff09;创建ASP.NET Web应用程式&#xff0c;如下图&#xff1a; &#xff08;2&#xff09;选择Empty,勾选Web API&#xff0c;点击确定创建&#xff0c;如下图&#xff1a; &#xff08;3&#x…

解决Netty那些事儿之Reactor在Netty中的实现(创建篇)-上

本系列Netty源码解析文章基于 4.1.56.Final版本 在上篇文章深入讲解Netty那些事儿之从内核角度看IO模型中我们花了大量的篇幅来从内核角度详细讲述了五种IO模型的演进过程以及ReactorIO线程模型的底层基石IO多路复用技术在内核中的实现原理。 最后我们引出了netty中使用的主从…

代码随想录刷题day52 300.最长递增子序列;674. 最长连续递增序列;718. 最长重复子数组

代码随想录刷题day52 300.最长递增子序列&#xff1b;674. 最长连续递增序列&#xff1b;718. 最长重复子数组 二维dp的初次应用&#xff0c;关于子序列的一系列问题。 300.最长递增子序列 300. 最长递增子序列 - 力扣&#xff08;Leetcode&#xff09; 子序列的一个入门题…

java中set接口、哈希表、哈希值、HashSet、LinkedHashSet、方法的可变参数

set接口&#xff1a; set接口和list接口一样&#xff0c;都是继承于Collection接口&#xff0c;它与Collection接口中的方法基本一致。特点&#xff1a;不允许存储重复元素&#xff0c;元素没有索引。它主要有两个实现类&#xff1a;HashSet&#xff08;具有哈希表结构&#x…

微服务框架 SpringCloud微服务架构 9 初识 Docker 9.2 Docker 与虚拟机的差别

微服务框架 【SpringCloudRabbitMQDockerRedis搜索分布式&#xff0c;系统详解springcloud微服务技术栈课程|黑马程序员Java微服务】 SpringCloud微服务架构 文章目录微服务框架SpringCloud微服务架构9 初识 Docker9.2 Docker 与虚拟机的差别9.2.1 Docker 与虚拟机9.2.2 总结…

基于Android的二维码识别系统的研究与实现(eclipse开发)

目 录 1 Android系统开发背景与意义 1 1.1 Android系统平台的出现 1 1.2 Android系统的发展 1 1.3 Android系统架构的介绍 1 1.4 Android开放系统 3 1.5 Android系统的特点 3 2 二维码识别系统背景介绍 3 2.1 二维码识别系统背景 3 2.1.1 二维码技术产生的背景 3 2.1.2 二维码分…

图像压缩原理-JPEG

搬来一个基础啊 给自己看~~ 非技术指正勿扰 图像的格式有很多种&#xff0c;比如PNG&#xff0c;JPEG等等&#xff0c;但当我们把一张图用工具变成各种其他格式时&#xff0c;其在计算机文件系统显示的文件大小各不一样&#xff0c;但是当你打开显示时&#xff0c;从视觉角度…

Android进阶之路 - Json解析异常

在App与H5交互时&#xff0c;有一个调原生分享的需求&#xff0c;交互方面没有问题&#xff0c;因为分享需要多值&#xff0c;所以采用json进行传递&#xff0c;在app接收进行解析时遇到了这个解析异常 Value &#xfeff; of type java.lang.String cannot be converted to JS…

【操作系统一】图解TCP/IP模型+实战

【操作系统一】OSI模型和TCP/IP模型一、OSI模型1、什么是OSI模型2、osi七层参考模型3、我更想介绍TCP/IP模型二、TCP/IP模型1、TCP/IP模型起源2、TCP/IP模型是五层还是四层&#xff1f;3、两层TCP/IP模型4、传输层&#xff08;也叫传输控制层&#xff09;4.1 TCP4.3、三次握手4…

【算法面试题汇总】LeetBook列表的算法面试题汇总---动态规划题目及答案

整理不易留个小心心呗&#x1f970; 如果有更好的或者是我有错的地方还请各位大佬指出哦 有些是copy的还望不要介意 动态规划至少有k个重复字符的最长子串二叉树中的最大路径和最长连续序列打家劫舍完全平方数最长上升子序列*零钱兑换矩阵中的最长递增路径至少有k个重复字符的最…

java计算机毕业设计ssm民宿管理系统设计7lky4(附源码、数据库)

java计算机毕业设计ssm民宿管理系统设计7lky4&#xff08;附源码、数据库&#xff09; 项目运行 环境配置&#xff1a; Jdk1.8 Tomcat8.5 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff0…