shell基础
设置根据后缀补充title
新建.vimrc文件,存放到家目录中
vim .vimrc
#做一些对vim的自定义设置
set cursorline
set autoindent
#当新建的文件以sh结尾的,调用SetTitel()函数
autocmd BufNewFile *.sh exec ":call SetTitle()"
#当新建的文件以hxg结尾的,调用HxgTitel()函数
autocmd BufNewFile *.hxg exec ":call HxgTitle()"
#定义SetTitle函数
func SetTitle()
if expand("%:e") == 'sh'
call setline(1,"#!/bin/bash")
call setline(2,"#")
call setline(3,"#")
call setline(4,"#Author: XXX")
call setline(5,"#QQ: 123456")
call setline(6,"#Date: ".strftime("%Y-%m-%d"))
call setline(7,"#FileName: ".expand("%") )
call setline(8,"#URL: http://xxxxxxxxxxxxxxxxx")
call setline(9,"#")
call setline(10,"#")
call setline(11," ")
endif
#函数结束
endfunc
#定函数HxgTitle函数
func HxgTitle()
if expand("%:e") == 'hxg'
call setline(1,"#!/bin/hxg")
call setline(2,"#")
call setline(3,"#")
call setline(4,"#Author: XXX")
call setline(5,"#QQ: 123456")
call setline(6,"#Date: ".strftime("%Y-%m-%d"))
call setline(7,"#FileName: ".expand("%") )
call setline(8,"#URL: http://xxxxxxxxxxxxxxxxx")
call setline(9,"#")
call setline(10,"#")
call setline(11," ")
endif
#函数结束的标志
endfunc
#结束后将光标放在结尾
autocmd BufNewFile * normal G
简单的代码
vim /data/hello.sh
#!/bin/bash
echo 'hello word!!'
运行代码
-
#bash hello.sh hello word!!
-
#先加执行权限 chmod +x /data/hello.sh #然后直接运行 hello.sh hello word!!
新建用户脚本
vim useradd.sh
#!/bin/bash
useradd $1
echo $2 | passwd --stdin $1 &>/dev/null
echo -e '新用户'$1'新建成功\n密码为'$2
运行代码
#文件加执行权限
chmod +x useradd.sh
#运行代码
useradd.sh test admin
新用户test新建成功
密码为admin
显示出电脑的基本信息
vim echo '用户:'`uname -n`
#!/bin/bash
#定义变量,方便随时更改颜色
c='1;36'
echo -e "用户:\033[${c}m`uname -n`\033[0m"
echo -e "系统:\033[${c}m`cat /etc/centos-release|cut -d' ' -f1,4`版本\033[0m"
echo -e "内核:\033[${c}m`uname -r`版本\033[0m"
echo -e "CPU个数:\033[${c}m`lscpu | grep ^CPU\(s\)|tr -s ' ' ':'|cut -d: -f2`个\033[0m"
echo -e "CPU型号:\033[${c}m`lscpu | grep ^型号名称|tr -s ' ' @|cut -d@ -f4,6`\033[0m"
echo -e "系统内存:\033[${c}m`free -h|grep Mem|tr -s ' '|cut -d' ' -f2`\033[0m"
echo -e "硬盘:\033[${c}m`lsblk |grep sda|head -1|tr -s ' '|cut -d' ' -f4`\033[0m"
chmod +x lspc.sh
lspc.sh
用户:hexug
系统:CentOS 7.7.1908版本
内核:3.10.0-1062.el7.x86_64版本
CPU个数:1个
CPU型号:i5-7200U@2.50GHz
系统内存:1.9G
硬盘:100G
备份的简单脚本
vim /data/bakup.sh
#!/bin/bash
cp -a /etc/ /data/etc-bakup-`date +%F`
echo 'etc文件夹备份成功!'
chmod +x /data/bakup.sh
bakup.sh
etc文件夹备份成功!
改进版
可以通过外部赋值的方法,灵活备份文件
vim /data/bakup.sh
#!/bin/bash
cp -av $1$2 /data/$2-bakup-`date +%F` && echo $1$2'文件夹备份成功!'
chmod +x /data/bakup.sh
#将需要备份的文件或者文件夹进行分割,前半部分是作为第一个变量,目录名作为第二个变量
bakup.sh /etc/ profile.d
/etc/profile.d文件夹备份成功!
shell脚本基础
格式要求:首行shebang机制
#!/bin/bash
#!/usr/bin/python
#!/usr/bin/perl
脚本调试
检测脚本中的语法错误
bash -n /data/1.sh
调试执行
bash -x /data/1.sh
赋值
增强型赋值:
+=, -=, *=, /=, %=
let varOPERvalue
例如:let count+=3
自加3后自赋值
自增,自减:
let var+=1
let var++
let var-=1
let var--
使用read命令来接受输入
使用read来把输入值分配给一个或多个shell变量
-p
指定要显示的提示-s
静默输入,一般用于密码-n N
指定输入的字符长度N-d '字符'
输入结束符-t N
TIMEOUT为N秒
read 从标准输入中读取值,给每个单词分配一个变量
所有剩余单词都被分配给最后一个变量
$ read a b c
1 2 3 4 5
$ echo $a
1
$ echo $b
2
$ echo $c
3 4 5
如果read后面没有跟变量,则把值赋给REPLY
$ read
ads
$ echo $REPLY
ads
read -p "Enter a filename: " FILE
鸡兔同笼
#!/bin/bash
read -p "请输入头的数量:" h
[[ ! "$h" =~ ^[0-9]+$ ]] && { echo '输入不合法';exit; }
read -p "请输入脚的数量:" f
[[ ! "$f" =~ ^[0-9]+$ ]] && { echo '输入不合法';exit; }
T=$[ f/2-h]
G=$[h-T]
echo -e "鸡的数量为$G\n兔的数量为$T"
jttl.sh
请输入头的数量:16
请输入脚的数量:44
鸡的数量为10
兔的数量为6
防止扩展
反斜线(\)会使随后的字符按原意解释
echo Your cost: \$5.00
Your cost: $5.00
加引号来防止扩展
单引号(’’)防止所有扩展
双引号(”“)也可防止扩展,但是以下情况例外:
$
(美元符号) 变量扩展
``` (反引号) 命令替换
`(反斜线) 禁止单个字符扩展
!
(叹号) 历史命令替换
shell登录两种方式
交互式登录:
(1)直接通过终端输入账号密码登录
(2)使用“su - UserName” 切换的用户
执行顺序:/etc/profile --> /etc/profile.d/*.sh --> ~/.bash_profile -->~/.bashrc --> /etc/bashrc
非交互式登录:
(1)su UserName
(2)图形界面下打开的终端
(3)执行脚本
(4)任何其它的bash实例
执行顺序: /etc/profile.d/*.sh --> /etc/bashrc -->~/.bashrc
Profile类
按功能划分,存在两类:
profile类和bashrc类
profile类:为交互式登录的shell提供配置
全局:/etc/profile, /etc/profile.d/*.sh
个人:~/.bash_profile
功用:
(1) 用于定义环境变量
(2) 运行命令或脚本
Bashrc类
bashrc类:为非交互式和交互式登录的shell提供配置
全局:/etc/bashrc
个人:~/.bashrc
功用:
(1) 定义命令别名和函数
(2) 定义本地变量
编辑配置文件生效
修改profile和bashrc文件后需生效
两种方法:
1重新启动shell进程
2 . 或source
例:
. ~/.bashrc
Bash 退出任务
保存在~/.bash_logout
文件中(用户)
在退出登录shell时运行
用于
• 创建自动备份
• 清除临时文件
命令替换
命令替换的两种格式:
`Linux 命令`
$( Linux 命令)
eval "Linux 命令"
例子:
echo `ps -ef|grep httpd`
echo $(ps -ef|grep httpd)
set 命令
可选参数
参数 | 说明 |
---|---|
-a | 标示已修改的变量,以供输出至环境变量 |
-b | 使被中止的后台程序立刻回报执行状态 |
-d | Shell预设会用杂凑表记忆使用过的指令,以加速指令的执行。使用-d参数可取消 |
-e | 若指令传回值不等于0,则立即退出shell |
-f | 取消使用通配符 |
-h | 自动记录函数的所在位置 |
-k | 指令所给的参数都会被视为此指令的环境变量 |
-l | 记录for循环的变量名称 |
-m | 使用监视模式 |
-n | 测试模式,只读取指令,而不实际执行 |
-p | 启动优先顺序模式 |
-P | 启动-P参数后,执行指令时,会以实际的文件或目录来取代符号连接 |
-t | 执行完随后的指令,即退出shell |
-u | 当执行时使用到未定义过的变量,则显示错误信息 |
-v | 显示shell所读取的输入值 |
-H shell | 可利用”!”加<指令编号>的方式来执行 history 中记录的指令 |
-x | 执行指令后,会先显示该指令及所下的参数 |
+<参数> | 取消某个set曾启动的参数。与-<参数> 相反 |
-o option | 特殊属性有很多,大部分与上面的可选参数功能相同,这里就不列了 |
$- 变量
h: hashall,打开这个选项后,Shell 会将命令所在的路径hash下来,避免每次都要查询。通过set +h将h选项关闭
i: interactive-comments,包含这个选项说明当前的 shell 是一个交互式的shell。所谓的交互式shell,在脚本中,i选项是关闭的。
m: monitor,打开监控模式,就可以通过Job control来控制进程的停止、继续,后台或者前台执行等。
B: braceexpand,大括号扩展
H: history,H选项打开,可以展开历史列表中的命令,可以通过!感叹号来完成,例如“!!”返回上最近的一个历史命令,“!n”返回第 n 个历史命令
脚本安全
set 命令
-u
有变量没有赋值就使用的时候,显示错误信息
等同set –o nounset
-e
脚本出错,不会再执行后续命令
等同set –o errexit
获取脚本当前绝对路径
方式一:
FOLDER_PATH = $(cd "$(dirname "$0")"; pwd)
1、shell脚本文件名称:$0
2、获取当前脚本的相对路径(.):dirname "$0"
3、获取当前脚本相对路径的值:
4、cd到当前路径(cd .): cd "
5、输出脚本的绝对路径: cd "
6、取脚本绝对路径的地址,并赋值给FOLDER_PATH, FOLDER_PATH =
方式二:
script_dir=$(dirname $(readlink -f $0))
信号捕捉trap
trap '触发指令' 信号
进程收到系统发出的指定信号后,将执行自定义指令,而不会执行原操作
trap '' 信号
忽略信号的操作
trap '-' 信号
恢复原信号的操作
trap -p
列出自定义信号操作
trap finish EXIT
当脚本退出时,执行finish函数
显示当前系统可用信号: kill –l 或者 trap -l
常用信号:man 7 signal
- SIGHUP 无须关闭进程而让其重读配置文件
- SIGINT 中止正在运行的进程;相当于Ctrl+c
- SIGQUIT 相当于ctrl+\
- SIGKILL 强制杀死正在运行的进程
- SIGTERM 终止正在运行的进程
- SIGCONT 继续运行
- SIGSTOP 后台休眠
指定信号的方法 : (1) 信号的数字标识:1, 2, 9
(2) 信号完整名称:SIGHUP
(3) 信号的简写名称:HUP
#!/bin/bash
trap 'echo "signal:SIGINT"' 2
trap -p
for((i=0;i<=10;i++))
do
sleep 1
echo $i
done
trap '' int
trap -p
for((i=11;i<=20;i++))
do
sleep 1
echo $i
done
trap '-' int
trap -p
for((i=21;i<=30;i++))
do
sleep 1
echo $i
done
数组
变量:存储单个元素的内存空间
数组:存储多个元素的连续的内存空间,相当于多个变量的集合
数组名和索引
索引:编号从0开始,属于数值索引
注意:索引可支持使用自定义的格式,而不仅是数值格式,即为关联索引,bash4.0版本之后开始支持
bash的数组支持稀疏格式(索引不连续)
声明数组:
declare -a ARRAY_NAME
declare -A ARRAY_NAME 关联数组
注意:两者不可相互转换
数组赋值
数组元素的赋值
(1) 一次只赋值一个元素
ARRAY_NAME[INDEX]=VALUE
weekdays[0]="Sunday"
weekdays[4]="Thursday"
(2) 一次赋值全部元素
ARRAY_NAME=("VAL1" "VAL2" "VAL3" ...)
(3) 只赋值特定元素
ARRAY_NAME=([0]="VAL1" [3]="VAL2" ...)
(4) 交互式数组值对赋值
read -a ARRAY
显示所有数组:declare -a
引用数组
引用数组元素
${ARRAY_NAME[INDEX]}
注意:省略[INDEX]表示引用下标为0的元素
引用数组所有元素
${ARRAY_NAME[*]}
${ARRAY_NAME[@]}
数组的长度(数组中元素的个数)
${#ARRAY_NAME[*]}
${#ARRAY_NAME[@]}
删除数组中的某元素:导致稀疏格式
unset ARRAY[INDEX]
删除整个数组
unset ARRAY
数组数据处理
引用数组中的元素:
数组切片:
${ARRAY[@]:offset:number}
offset 要跳过的元素个数
number 要取出的元素个数
取偏移量之后的所有元素
${ARRAY[@]:offset}
向数组中追加元素:
ARRAY[${#ARRAY[*]}]=value
关联数组:
declare -A ARRAY_NAME
ARRAY_NAME=([idx_name1]='val1' [idx_name2]='val2‘...)
注意:关联数组必须先声明再调用
冒泡排序,对数据进行排序
#!/bin/bash
for i in `seq 10`;do
a[i]=$RANDOM
done
echo "原数据:${a[*]}"
for n in `seq 2 10`;do
for j in `seq 2 $[12-n]`;do
if [ ${a[$j]} -lt ${a[$[j-1]]} ];then
a[$j]=$((a[$j]^a[$[j-1]]))
a[$((j-1))]=$((a[$j]^a[$((j-1))]))
a[$j]=$((a[$j]^a[$[j-1]]))
fi
done
done
max=${a[10]}
min=${a[1]}
echo "排序后:${a[*]}"
echo -e "最大值为${max}\n最小值为${min}"
杨辉三角
#!/bin/bash
#
#
#Author: XXX
#QQ: 123456
#Date: 2021-05-26
#FileName: yanghui.sh
#URL: http://https://XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
#
#
for i in `seq $1`;do
if [ $i -eq 1 ];then
a[11]=1
echo 1
else
for j in `seq $i`;do
if [ $j -eq 1 -o $j -eq $i ];then
a[${i}$j]=1
else
a[${i}$j]=$((a[$[i-1]$[j-1]]+a[$[i-1]$j]))
fi
echo -n -e "${a[${i}$j]}\t"
done
echo
fi
done
字符串
切片
表达式 | 含义 |
---|---|
${#var} |
返回字符串变量var的长度 |
${var:m} | 返回${var} 中从第m个字符到最后的部分 |
|
${var:m:len} |返回${var} 中从第m个字符开始,长度为len的部分 |
|
${var#pattern} | 删除${var} 中开头部分与pattern匹配的最小部分 |
|
${var##pattern} | 删除${var} 中开头部分与pattern匹配的最大部分 |
|
${var%pattern} | 删除${var} 中结尾部分与pattern匹配的最小部分 |
|
${var%%pattern} | 删除${var} 中结尾部分与pattern匹配的最大部分 |
${#var}
:返回字符串变量var的长度
name=abcdefg
echo ${#name}
7
${var:offset}
:返回字符串变量var中从第offset个字符后(不包括第offset个字符)的字符开始,到最后的部分,offset的取值在0 到 ${#var}-1 之间(bash4.2后,允许为负值)
echo ${name:2}
cdefg
${var:offset:number}
:返回字符串变量var中从第offset个字符后(不包括第offset个字符)的字符开始,长度为number的部分
echo ${name:2:3}
cde
${var: -length}
:取字符串的最右侧几个字符
注意:冒号后必须有一空白字符
echo ${name: -2}
fg
${var:offset:-length}
:从最左侧跳过offset字符,一直向右取到距离最右侧lengh个字符之前的内容
抛头去尾
#去掉前2个和后3个
echo ${name:2:-3}
cd
${var: -length:-offset}
:先从最右侧向左取到length个字符开始,再向右取到距离最右侧offset个字符之间的内容
注意:-length前空格
#后5个里面去掉后3个
echo ${name: -5:-3}
cd
$ s=abacsbdbac
$ echo ${s%b*c}
abacsbd
$ echo ${s%%b*c}
a
字符串处理
#* 是将字符串从左往右删,一直删到包括字符串
##* 贪婪模式从左往右删
%* 是从右往左删,包括字符串
%%* 贪婪模式从右往左删
基于模式取子串
${var#*word}
:其中word可以是指定的任意字符
功能:自左而右,查找var变量所存储的字符串中,第一次出现的word, 删除字符串开头至第一次出现word字符串(含)之间的所有字符
${var##*word}
:同上,贪婪模式,不同的是,删除的是字符串开头至最后一次由word指定的字符之间的所有内容
示例:
file=“var/log/messages”
${file#*/}: log/messages
${file##*/}: messages
${var%word*}
:其中word可以是指定的任意字符
功能:自右而左,查找var变量所存储的字符串中,第一次出现的word, 删除字符串最后一个字符向左至第一次出现word字符串(含)之间的所有字符
file="/var/log/messages"
${file%/*}: /var/log
${var%%word*}
:同上,只不过删除字符串最右侧的字符向左至最后一次出现word字符之间的所有字符
示例:
url=http://www.magedu.com:80
${url##*:} 80
${url%%:*} http
查找替换
${var/pattern/substr}
:查找var所表示的字符串中,第一次被pattern所匹配到的字符串,以substr替换之
${var//pattern/substr}
: 查找var所表示的字符串中,所有能被pattern所匹配到的字符串,以substr替换之
${var/#pattern/substr}
:查找var所表示的字符串中,行首被pattern所匹配到的字符串,以substr替换之
是位置锚定,行首
${var/%pattern/substr}
:查找var所表示的字符串中,行尾被pattern所匹配到的字符串,以substr替换之
%是位置锚定,行尾
查找并删除
${var/pattern}
:删除var表示的字符串中第一次被pattern匹配到的字符串
${var//pattern}
:删除var表示的字符串中所有被pattern匹配到的字符串
${var/#pattern}
:删除var表示的字符串中所有以pattern为行首匹配到的字符串
${var/%pattern}
:删除var所表示的字符串中所有以pattern为行尾所匹配到的字符串
字符大小写转换
${var^^}
:把var中的所有小写字母转换为大写
${var,,}
:把var中的所有大写字母转换为小写
变量赋值
高级变量用法-有类型变量
Shell变量一般是无类型的,但是bash Shell提供了declare和typeset两个命令用于指定变量的类型,两个命令是等价的
declare [选项] 变量名
-r 声明或显示只读变量
-i 将变量定义为整型数
-a 将变量定义为数组
-A 将变量定义为关联数组
-f 显示已定义的所有函数名及其内容
-F 仅显示已定义的所有函数名
-x 声明或显示环境变量和函数
-l 声明变量为小写字母 declare –l var=UPPER
-u 声明变量为大写字母 declare –u var=lower
eval命令
eval命令将会首先扫描命令行进行所有的置换,然后再执行该命令。该命令适用于那些一次扫描无法实现其功能的变量.该命令对变量进行两次扫描
示例:
$ CMD=whoami
$ echo $CMD
whoami
$ eval $CMD
root
$ n=10
$ echo {0..$n}
{0..10}
$ eval echo {0..$n}
0 1 2 3 4 5 6 7 8 9 10
间接变量引用
bash Shell提供了两种格式实现间接变量引用
eval tempvar=\$$variable1
tempvar=${!variable1}
示例
$ N=NAME
$ NAME=wangxiaochun
$ N1=${!N}
$ echo $N1
wangxiaochun
$ eval N2=\$$N
$ echo $N2
wangxiaochun
创建临时文件
mktemp命令:创建并显示临时文件,可避免冲突
mktemp [OPTION]... [TEMPLATE]
TEMPLATE: filenameXXX
X至少要出现三个
OPTION:
-d: 创建临时目录
-p DIR或--tmpdir=DIR:指明临时文件所存放目录位置
示例
mktemp /tmp/testXXX
tmpdir=`mktemp –d /tmp/testdirXXX`
mktemp --tmpdir=/testdir testXXXXXX
安装复制文件
install命令:
install [OPTION]... [-T] SOURCE DEST 单文件
install [OPTION]... SOURCE... DIRECTORY
install [OPTION]... -t DIRECTORY SOURCE...
install [OPTION]... -d DIRECTORY...创建空目录
选项:
-m MODE,默认755
-o OWNER
-g GROUP
示例
install -m 700 -o wang -g admins srcfile desfile
install –m 770 –d /testdir/installdir
本文来自博客园,作者:厚礼蝎,转载请注明原文链接:https://www.cnblogs.com/guangdelw/p/17147785.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· .NET Core 中如何实现缓存的预热?
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 如何调用 DeepSeek 的自然语言处理 API 接口并集成到在线客服系统
· 【译】Visual Studio 中新的强大生产力特性