[root@rocky01 ~]# cat .vimrc
set ts=4
set et
autocmd BufNewFile *.sh,*.script exec ":call SetTitle()"
function SetTitle()
if expand("%:e") == "sh"
call setline(1,"#!/bin/bash")
call setline(2," ")
call setline(3,"#******************************************************")
call setline(4,"# Author: 会不会有那么一天 ")
call setline(5,"# QQ: 791270697 ")
call setline(6,"# Date: ".strftime("%Y-%m-%d ")." ")
call setline(7,"# FileName: ".expand("%")." ")
call setline(8,"# Version: 1.0.0 ")
call setline(9,"# Description: The test script ")
call setline(10,"# BLOG: https://www.cnblogs.com/Willoneday ")
call setline(11,"#******************************************************")
call setline(12,"")
call setline(13,"")
endif
endfunc
autocmd BufNewFile * normal G
[root@rocky01 ~]# mv hello.sh /data/httpd-2.4.54/htdocs/
[root@rocky01 ~]# hostname -I
10.0.0.128
[root@rocky01 ~]# curl 10.0.0.128/hello.sh
#!/bin/bash
echo 'Hello, world!'
#方法一
[root@rocky01 ~]# curl 10.0.0.128/hello.sh 2> /dev/null |bash
Hello, world!
#方法二
[root@rocky01 ~]# curl -s 10.0.0.128/hello.sh |bash
Hello, world!
[root@ubuntu01 ~]# hostname -I
10.0.0.129
[root@ubuntu01 ~]# cat work2.sh
echo "我在`hostname -I`上运行"
[root@ubuntu01 ~]#
[root@ubuntu01 ~]# ssh 10.0.0.128 /bin/bash < work2.sh
root@10.0.0.128's password:
我在10.0.0.128 上运行
bash -n ScriptName.sh 只检测脚本中的语法错误,但无法检查出命令错误,但不真正执行脚本
bash -x ScriptName.sh 调试并执行
总结:脚本错误常见的有三种
- 语法错误:会导致后续的命令不继续执行,可以用bash -n 检查错误,提示的出错行数不一定是准确的
- 命令错误:默认后续的命令还会继续执行,用bash -n 无法检查出来 ,可以使用 bash -x 进行观察
- 逻辑错误:只能使用 bash -x 进行观察
变量的生效范围等标准划分变量类型
name='root'name="$USER"name=`COMMAND` 或者 name=$(COMMAND)$name${name}弱引用和强引用
- "$name" 弱引用,其中的变量引用会被替换为变量值
- '$name' 强引用,其中的变量引用不会被替换为变量值,而保持原字符串
[root@rocky01 ~]# NUM=`seq 3`
[root@rocky01 ~]# echo $NUM
1 2 3
[root@rocky01 ~]# echo "$NUM"
1
2
3
[root@rocky01 ~]# echo '$NUM'
$NUM
[root@rocky01 ~]# TITLE=Willoneday
[root@rocky01 ~]# TITLE+=:Yes
[root@rocky01 ~]# echo $TITLE
Willoneday:Yes
unset <name>
[root@rocky01 ~]# cat system_info.sh
#!/bin/bash
#******************************************************
# Author: 会不会有那么一天
# QQ: 791270697
# Date: 2022-08-07
# FileName: system_info.sh
# Version: 1.0.0
# Description: The test script
# BLOG: https://www.cnblogs.com/Willoneday
#******************************************************
RED="\E[1;31m"
GREEN="echo -e \E[1;32m"
END="\E[0m"
. /etc/os-release
$GREEN----------------------Host systeminfo--------------------$END
echo -e "HOSTNAME: $RED`hostname`$END"
echo -e "IPADDR: $RED` hostname -I`$END"
echo -e "OSVERSION: $RED$PRETTY_NAME$END"
echo -e "KERNEL: $RED`uname -r`$END"
echo -e "CPU: $RED`lscpu|grep '^Model name'|tr -s ' '|cut -d : -f2` $END"
echo -e "MEMORY: $RED`free -h|grep Mem|tr -s ' ' : |cut -d : -f2`$END"
echo -e "DISK: $RED`lsblk |grep '^sd' |tr -s ' ' |cut -d " " -f4`$END"
$GREEN---------------------------------------------------------$END

- 可以使子进程(包括孙子进程)继承父进程的变量,但是无法让父进程使用子进程的变量
- 一旦子进程修改从父进程继承的变量,将会新的值传递给孙子进程
- 一般只在系统配置文件中使用,在脚本中较少使用
显示所有环境变量:
- env
- printenv
- export
- declare -x
bash内的环境变量
- PATH
- SHELL
- USER
- UID
- HOME
- PWD
- SHLVL #shell的嵌套层数,即深度
- LANG
- HOSTNAME
- HISTSIZE
- _ #下划线,表示前一命令的最后一个参数
在bash shell中内置的变量, 在脚本代码中调用通过命令行传递给脚本的参数
- $1, $2, ... 对应第1个、第2个等参数,shift [n]换位置
- $0 shell脚本本身的名字
- $* 传递给脚本的所有参数,全部参数合为一个字符串
- $@ 传递给脚本的所有参数,每个参数为独立字符串
- $# 传递给脚本的参数的个数
注意:$@ $* 只在被双引号包起来的时候才会有差异
$?的值为0 #代表成功
$?的值是1到255 #代表失败
用户可以在脚本中使用以下命令自定义退出状态码 exit n
注意:
- 脚本中一旦遇到exit命令,脚本会立即终止;终止退出状态取决于exit命令后面的数字
- 如果exit后面无数字,终止退出状态取决于exit命令前面命令执行结果
- 如果没有exit命令, 即未给脚本指定退出状态码,整个脚本的退出状态码取决于脚本中执行的最后一条命令的状态码
$RANDOM 取值范围:0-32767
[root@rocky01 ~]# echo $[$RANDOM%50]
[root@rocky01 ~]# echo -e "\033[1;$[RANDOM%7+31]mWilloneday\033[0m"
注意:bash 只支持整数,不支持小数
实现算术运算:
- (1) let var=算术表达式
- (2) ((var=算术表达式)) 和(1)等价
- (3) var=$[算术表达式]
- (4) var=$((算术表达式))
- (5) var=$(expr arg1 arg2 arg3 ...)
- (6) declare -i var = 数值
- (7) echo '算术表达式' | bc
let i+=1
let i++
let i-=1
let i--
[root@rocky01 ~]# i=1; let j=i++; echo "i=$i,j=$j"
i=2,j=1
[root@rocky01 ~]# i=1; let j=++i; echo "i=$i,j=$j"
i=2,j=2
- 与:& 一假则假,全真才真
- 或:| 一真则真,全假才假
- 非:!
- 异或:^ 异或的两个值,相同为假,不同为真。两个数字X,Y异或得到结果Z,Z再和任意两者之一X异或,将得出另一个值Y
[root@rocky01 ~]# x=10;y=20;x=$[x^y];y=$[x^y];x=$[x^y];echo x=$x,y=$y
x=20,y=10
短路与 &&
CMD1 && CMD2
第一个CMD1结果为真(1),第二个CMD2必须要参与运算,才能得到最终的结果
第一个CMD1结果为假(0),总的结果必定为0,因此不需要执行CMD2
CMD1 || CMD2
第一个CMD1结果为真(1),总的结果必定为1,因此不需要执行CMD2
第一个CMD1结果为假(0),第二个CMD2 必须要参与运算,才能得到最终的结果
CMD1 && CMD2 || CMD3
当CMD1执行成功时,会执行CMD2
当CMD1执行失败时,会执行CMD3
条件测试:判断某需求是否满足,需要由测试机制来实现,专用的测试表达式需要由测试命令辅助完成测试过程,实现评估布尔声明,以便用在条件性环境下进行执行
- 若真,则状态码变量 $? 返回0
- 若假,则状态码变量 $? 返回
条件测试命令
- test EXPRESSION
- [ EXPRESSION ] #和test 等价,建议使用 [ ]
- [[ EXPRESSION ]] 相关于增强版的 [ ], 支持[]的用法,且支持扩展正则表达式和通配符
注意:EXPRESSION前后必须有空白字符
#判断 NAME 变量是否定义
[ -v NAME ]
- -eq 等于
- -ne 不等于
- -gt 大于
- -ge 大于等于
- -lt 小于
- -le 小于等于
- [ -z STRING ] 字符串没定义或空为真,不空为假,
- [ -n STRING ] 字符串不空为真,空为假
- [ STRING ] 字符串不空为真,空为假
- [ STRING1 = STRING2 ] 是否等于,注意 = 前后有空格
- [ STRING1 != STRING2 ] 是否不等于
注意:在比较字符串时,建议变量放在“ ”中
[[ == ]] 左侧字符串是否和右侧的PATTERN相同
注意:此表达式用于 == 右侧为通配符
[[ =~ ]] 左侧字符串是否能够被右侧的正则表达式的PATTERN所匹配
注意: 此表达式用于 =~ 右侧为扩展的正则表达式
注意:[[ == ]] == 右侧的 * 做为通配符,不要加“”,只想做为*符号使用时, 需要加 “” 或转义
建议:当使用正则表达式或通配符使用[[ ]],其它情况一般使用 [ ]
[root@rocky01 ~]# echo $NAME
[root@rocky01 ~]# [ -n "$NAME" ]
[root@rocky01 ~]# echo $?
1
[root@rocky01 ~]# NAME=Willoneday
[root@rocky01 ~]# [ -n "$NAME" ]
[root@rocky01 ~]# echo $?
0
[root@rocky01 ~]# [ "$NAME" ]
[root@rocky01 ~]# echo $?
0
#通配符*
[root@rocky01 ~]# FILE="Will*"
[root@rocky01 ~]# [[ $FILE == W* ]]
[root@rocky01 ~]# echo $?
0
#通配符?
[root@rocky01 ~]# FILE="Will"
[root@rocky01 ~]# [[ $FILE == ???? ]]
[root@rocky01 ~]# echo $?
0
[root@rocky01 ~]# [[ $FILE == ??? ]]
[root@rocky01 ~]# echo $?
1
#引号
#结论:[[ == ]] == 右侧的 * 做为通配符,不要加 " " ,只想做为*符号使用时, 需要加 " " 或转义
[root@rocky01 ~]# NAME="linux1"
[root@rocky01 ~]# [[ "$NAME" == linux* ]]
[root@rocky01 ~]# echo $?
0
[root@rocky01 ~]# [[ "$NAME" == "linux*" ]]
[root@rocky01 ~]# echo $?
1
[root@rocky01 ~]# NAME="linux*"
[root@rocky01 ~]# [[ "$NAME" == "linux*" ]]
[root@rocky01 ~]# echo $?
0
[root@rocky01 ~]# [[ $SCORE =~ ^(100|[0-9]{1,2})$ ]]
[root@rocky01 ~]# [[ "$N" =~ ^[0-9]+$ ]]
[root@rocky01 ~]# [[ "$IP" =~ ^([0-9]{1,3}\.){3}[0-9]{1,3}$ ]]
- -a FILE:同 -e,建议使用-e
- -e FILE: 文件存在性测试,存在为真,否则为假
- -b FILE:是否存在且为块设备文件
- -c FILE:是否存在且为字符设备文件
- -d FILE:是否存在且为目录文件
- -f FILE:是否存在且为普通文件
- -h FILE:或 -L FILE:存在且为符号链接文件
- -p FILE:是否存在且为命名管道文件
- -S FILE:是否存在且为套接字文件
- -r FILE:是否存在且可读
- -w FILE: 是否存在且可写
- -x FILE: 是否存在且可执行
- -u FILE:是否存在且拥有suid权限
- -g FILE:是否存在且拥有sgid权限
- -k FILE:是否存在且拥有sticky权限
注意:最终结果由用户对文件的实际权限决定,而非文件属性决定
(CMD1;CMD2;...)和 { CMD1;CMD2;...; } 都可以将多个命令组合在一起,批量执行
( list ) 会开启子shell,并且list中变量赋值及内部命令执行后,将不再影响后续的环境
{ list } 不会启子shell,在当前shell中运行,会影响当前shell环境
范例
[root@rocky01 ~]# name=Willoneday;( echo $name;name=Dream;echo $name );echo $name
Willoneday
Dream
Willoneday
[root@rocky01 ~]# name=Willoneday;{ echo $name;name=Dream;echo $name; };echo $name
Willoneday
Dream
Dream
[ EXPRESSION1 -a EXPRESSION2 ]#并且,EXPRESSION1和EXPRESSION2都是真,结果才为真[ EXPRESSION1 -o EXPRESSION2 ]#或者, EXPRESSION1和EXPRESSION2只要有一个真,结果就为真[ ! EXPRESSION ]#取反说明: -a 和 -o 需要使用测试命令进行,[[ ]] 不支持
COMMAND1 && COMMAND2#并且,短路与,代表条件性的AND THEN如果COMMAND1 成功,将执行COMMAND2,否则,将不执行COMMAND2
COMMAND1 || COMMAND2#或者,短路或,代表条件性的OR ELSE如果COMMAND1 成功,将不执行COMMAND2,否则,将执行COMMAND2
! COMMAND#非,取反
[root@rocky01 ~]# getent passwd Willoneday
[root@rocky01 ~]# id Willoneday &> /dev/null || useradd Willoneday
[root@rocky01 ~]# getent passwd Willoneday
Willoneday:x:1001:1001::/home/Willoneday:/bin/bash
[root@rocky01 ~]# cat ip.sh
#!/bin/bash
#******************************************************
# Author: 会不会有那么一天
# QQ: 791270697
# Date: 2022-08-07
# FileName: ip.sh
# Version: 1.0.0
# Description: The test script
# BLOG: https://www.cnblogs.com/Willoneday
#******************************************************
ip=`hostname -I`
ping $ip -c 1 &> /dev/null && echo "$ip在线" || echo "$ip不在线"
ip2=1.1.1.1
ping $ip2 -c 1 &> /dev/null && echo "$ip2在线" || echo "$ip2不在线"
[root@rocky01 ~]# bash ip.sh
10.0.0.128 在线
1.1.1.1不在线
[root@rocky01 ~]# . /etc/os-release; [[ $ID == "rocky" ]] && [[ $VERSION_ID == 8* ]] && echo Rocky8 || echo NO Rocky8
Rocky8
[root@rocky01 ~]# cat disk_check.sh
#!/bin/bash
#******************************************************
# Author: 会不会有那么一天
# QQ: 791270697
# Date: 2022-08-07
# FileName: disk_check.sh
# Version: 1.0.0
# Description: The test script
# BLOG: https://www.cnblogs.com/Willoneday
#******************************************************
WARNING=80
SPACE_USED=`df|grep '^/dev/sd'|tr -s ' ' %|cut -d% -f5|sort -nr|head -1`
[ "$SPACE_USED" -ge $WARNING ] && echo "disk used is $SPACE_USED,will be full" | mail -s diskwaring root
使用read来把输入值分配给一个或多个shell变量,read从标准输入中读取值,给每个单词分配一个变量,所有剩余单词都被分配给最后一个变量,如果变量名没有指定,默认标准输入的值赋值给系统内置变量REPLY
常见选项
- -p 指定要显示的提示
- -s 静默输入,一般用于密码
- -n N 指定输入的字符长度N
- -d '字符' 输入结束符
- -t N TIMEOUT为N秒
[root@rocky01 ~]# read
Willoneday
[root@rocky01 ~]# echo $REPLY
Willoneday
[root@rocky01 ~]# read NAME AGE
Willoneday 20
[root@rocky01 ~]# echo $NAME
Willoneday
[root@rocky01 ~]# echo $AGE
20
[root@rocky01 ~]# cat test.txt
1 2
[root@rocky01 ~]# read i j < test.txt ; echo i=$i j=$j
i=1 j=2
[root@rocky01 ~]# echo 1 2 | read x y ; echo x=$x y=$y
x= y=
[root@rocky01 ~]# echo 1 2 | ( read x y ; echo x=$x y=$y )
x=1 y=2
[root@rocky01 ~]# echo 1 2 | { read x y ; echo x=$x y=$y; }
x=1 y=2
[root@rocky01 ~]# read -p "Are you rich?yes or no: " ANSWER
Are you rich?yes or no: yes
[root@rocky01 ~]# [[ $ANSWER =~ ^([Yy]|[Yy][Ee][Ss])$ ]] && echo "You are rich" || echo "No"
You are rich
针对所有用户皆有效
- /etc/profile
- /etc/profile.d/*.sh
- /etc/bashrc
只针对特定用户有效
~/.bashrc
~/.bash_profile
su - UserNamesu UserName
profile类为交互式登录的shell提供配置
全局:/etc/profile, /etc/profile.d/*.sh
个人:~/.bash_profile
功用:
(1) 用于定义环境变量
(2) 运行命令或脚本
为非交互式和交互式登录的shell提供配置
全局:/etc/bashrc
个人:~/.bashrc
功用:
(1) 定义命令别名和函数
(2) 定义本地变量
if COMMANDS; then COMMANDS; [ elif COMMANDS; then COMMANDS; ]... [ else COMMANDS; ] fi
if 判断条件;then
条件为真的分支代码
fi
if 判断条件; then
条件为真的分支代码
else
条件为假的分支代码
fi
if 判断条件1; then
条件1为真的分支代码
elif 判断条件2; then
条件2为真的分支代码
elif 判断条件3; then
条件3为真的分支代码
...
else
以上条件都为假的分支代码
fi
[root@rocky01 ~]# cat bmi.sh
#!/bin/bash
#******************************************************
# Author: 会不会有那么一天
# QQ: 791270697
# Date: 2022-08-08
# FileName: bmi.sh
# Version: 1.0.0
# Description: The test script
# BLOG: https://www.cnblogs.com/Willoneday
#******************************************************
read -p "请输入身高(m为单位): " HIGH
if [[ ! "$HIGH" =~ ^[0-2](\.[0-9]{,2})?$ ]];then
echo "输入错误的身高!"
exit 1
fi
read -p "请输入体重(kg为单位): " WEIGHT
if [[ ! "$WEIGHT" =~ ^[0-9]{1,3}$ ]];then
echo "输入错误的体重!";
exit 2;
fi
BMI=`echo $WEIGHT/$HIGH^2|bc`
if [ $BMI -le 18 ];then
echo "太瘦了,多吃点!"
elif [ $BMI -lt 24 ];then
echo "身材很棒!"
else
echo "太胖了,注意节食,加强运动!"
fi
case: case WORD in [PATTERN [| PATTERN]...) COMMANDS ;;]... esac
case 变量引用 in
PAT1)
分支1
;;
PAT2)
分支2
;;
...
*)
默认分支
;;
esac
case支持glob风格的通配符:
- * 任意长度任意字符
- ? 任意单个字符
- [ ] 指定范围内的任意单个字符
- | 或者,如: a|b
[root@rocky01 ~]# cat yes-no.sh
#!/bin/bash
#******************************************************
# Author: 会不会有那么一天
# QQ: 791270697
# Date: 2022-08-08
# FileName: yes-no.sh
# Version: 1.0.0
# Description: The test script
# BLOG: https://www.cnblogs.com/Willoneday
#******************************************************
read -p "Do you agree(yes/no)? " INPUT
case $INPUT in
[yY]|[Yy][Ee][Ss])
echo "You input is YES"
;;
[Nn]|[Nn][Oo])
echo "You input is NO"
;;
*)
echo "Input fales,please input yes or no!"
;;
esac
for NAME [in WORDS ... ] ; do COMMANDS; done
for 变量名 in 列表
do
循环体
done
执行机制
- 依次将列表中的元素赋值给“变量名”; 每次赋值后即执行一次循环体; 直到列表中的元素耗尽,循环结束
- 如果省略 [in WORDS ... ] ,此时使用位置参数变量 in "$@
for ((: for (( exp1; exp2; exp3 )); do COMMANDS; done
for((控制变量初始化;条件判断表达式;控制变量的修正表达式))
do
循环体
done
[root@rocky01 ~]# sum=0;for i in {1..100..2};do let sum+=i;done;echo sum=$sum
sum=2500
[root@rocky01 ~]# cat for-sum.sh
#!/bin/bash
#******************************************************
# Author: 会不会有那么一天
# QQ: 791270697
# Date: 2022-08-08
# FileName: for-sum.sh
# Version: 1.0.0
# Description: The test script
# BLOG: https://www.cnblogs.com/Willoneday
#******************************************************
sum=0
for i in $@;
do
let sum+=i
done
echo sum=$sum
[root@rocky01 ~]#
[root@rocky01 ~]# bash for-sum.sh 1 2 3 10
sum=16
#1.先创建好环境
[root@rocky01 opt]# cat create_dir.sh
#!/bin/bash
PDIR=/data/test
for i in {1..365};
do
#创建过去365天的目录
DIR=`date -d "-$i day" +%F`
mkdir -p $PDIR/$DIR
#随机创建10个文件
for j in {1..10};
do
touch $PDIR/$DIR/$RANDOM.log
done
done
#2.开始移动
[root@rocky01 opt]# cat mv_file.sh
#!/bin/bash
PDIR=/data/test
cd $PDIR || { echo 无法进入 $PDIR;exit 1; }
for DIR in *;
do
YYYY_MM=`echo $DIR |cut -d "-" -f 1,2`
DD=`echo $DIR |cut -d "-" -f 3`
[ -d $YYYY_MM/$DD ] || mkdir -p $YYYY_MM/$DD &> /dev/null
mv $DIR/* $YYYY_MM/$DD
done
rm -rf $PDIR/*-*-*
[root@rocky01 ~]# for((i = 0; i <= 100; ++i)); do printf "\e[4D%3d%%" $i;sleep 0.01s; done
100%
while COMMANDS; do COMMANDS; done
while CONDITION;
do
循环体
done
说明
- 进入条件:CONDITION为 true
- 退出条件:CONDITION为 false
while true;
do
循环体
done
while [ true ];
do
循环体
done
while 循环的特殊用法,遍历文件或文本的每一行
while read line; do
循环体
done < /PATH/FILE
#依次读取/PATH/FILE文件中的每一行,且将行赋值给变量line
[root@rocky01 ~]# cat while_read_passwd.sh
#!/bin/bash
#******************************************************
# Author: 会不会有那么一天
# QQ: 791270697
# Date: 2022-08-08
# FileName: while_read_passwd.sh
# Version: 1.0.0
# Description: The test script
# BLOG: https://www.cnblogs.com/Willoneday
#******************************************************
while read line;
do
if [[ ! "$line" =~ /sbin/nologin$ ]];then
echo $line | cut -d: -f1,3
fi
done < /etc/passwd
[root@rocky01 ~]# bash while_read_passwd.sh
root:0
sync:5
shutdown:6
halt:7
rye:1000
Willoneday:1001
until COMMANDS; do COMMANDS; done
until CONDITION;
do
循环体
done
说明:
- 进入条件: CONDITION 为false
- 退出条件: CONDITION 为tru
执行条件和while相反,所以一般用while
continue [N]:提前结束第N层的本轮循环,而直接进入下一轮判断;最内层为第1层
while CONDITION1;
do
CMD1
...
if CONDITION2;then
continue
fi
CMDn
...
done
#有continue的效果
[root@rocky01 ~]# cat continue_yes.sh
#!/bin/bash
for((j=1;j<=3;j++))
do
for((i=1;i<=3;i++));
do
[ $i -eq 2 ] && continue 2
echo j=$j,i=$i
done
done
[root@rocky01 ~]# bash continue_yes.sh
j=1,i=1
j=2,i=1
j=3,i=1
#无continue的效果
[root@rocky01 ~]# cat continue_no.sh
#!/bin/bash
for((j=1;j<=3;j++))
do
for((i=1;i<=3;i++));
do
echo j=$j,i=$i
done
done
[root@rocky01 ~]# bash continue_no.sh
j=1,i=1
j=1,i=2
j=1,i=3
j=2,i=1
j=2,i=2
j=2,i=3
j=3,i=1
j=3,i=2
j=3,i=3
break [N]:提前结束第N层整个循环,最内层为第1层
while CONDITION1;
do
CMD1
...
if CONDITION2;then
break
fi
CMDn
...
done
#break第一层
[root@rocky01 ~]# cat break_yes1.sh
#!/bin/bash
for((j=1;j<=3;j++))
do
for((i=1;i<=3;i++));
do
[ $i -eq 2 ] && break 1
echo j=$j,i=$i
done
done
[root@rocky01 ~]# bash break_yes1.sh
j=1,i=1
j=2,i=1
j=3,i=1
#break第二层
[root@rocky01 ~]# cat break_yes2.sh
#!/bin/bash
for((j=1;j<=3;j++))
do
for((i=1;i<=3;i++));
do
[ $i -eq 2 ] && break 2
echo j=$j,i=$i
done
done
[root@rocky01 ~]# bash break_yes2.sh
j=1,i=1
说明
shift [n] 用于将参量列表 list 左移指定次数,缺省为左移一次。
参量列表 list 一旦被移动,最左端的那个参数就从列表中删除。while 循环遍历位置参量列表时,常用到 shift
[root@rocky01 ~]# cat shift_user.sh
#!/bin/bash
#******************************************************
# Author: 会不会有那么一天
# QQ: 791270697
# Date: 2022-08-08
# FileName: shift_user.sh
# Version: 1.0.0
# Description: The test script
# BLOG: https://www.cnblogs.com/Willoneday
#******************************************************
#检测是否有参数
if [ $# -eq 0 ];then
echo "Usage: $0 user1 user2 ..."
exit
fi
#检测用户是否存在
while [ "$1" ];do
if id $1 &> /dev/null;then
echo "$1 is exist"
else
echo "$1 is no exist"
fi
shift
done
[root@rocky01 ~]# bash shift_user.sh
Usage: shift_user.sh user1 user2 ...
[root@rocky01 ~]# bash shift_user.sh root Willoneday qqq
root is exist
Willoneday is exist
qqq is no exist
select NAME [in WORDS ... ;] do COMMANDS; done
select NAME in list;
do
循环体命令
done
说明:
- select 循环主要用于创建菜单,按数字顺序排列的菜单项显示在标准错误上,并显示 PS3 提示符,等待用户输入
- 用户输入菜单列表中的某个数字,执行相应的命令
- 用户输入菜单列表中的某个数字,会将对应的WORD值赋值给NAME变量
- 用户输入被保存在内置变量 REPLY 中
- select 是个无限循环,因此要用 break 命令退出循环,或用 exit 命令终止脚本。也可以按 ctrl+c退出循环
- select 经常和 case 联合使用
- 与 for 循环类似,可以省略 in list,此时使用位置参量
范例:菜单
[root@rocky01 ~]# cat select.sh
#!/bin/bash
#******************************************************
# Author: 会不会有那么一天
# QQ: 791270697
# Date: 2022-08-08
# FileName: select.sh
# Version: 1.0.0
# Description: The test script
# BLOG: https://www.cnblogs.com/Willoneday
#******************************************************
sum=0
PS3="请点菜(1-3): "
select MENU in 北京烤鸭 小龙虾 点菜结束;
do
case $REPLY in
1)
echo $MENU 价格是 100
let sum+=100
;;
2)
echo $MENU 价格是 88
let sum+=88
;;
3)
echo "点菜结束,退出"
break
;;
*)
echo "点菜错误,重新选择"
;;
esac
done
echo "总价格是: $sum"
[root@rocky01 ~]# bash select.sh
1) 北京烤鸭
2) 小龙虾
3) 点菜结束
请点菜(1-3): 1
北京烤鸭 价格是 100
请点菜(1-3): 2
小龙虾 价格是 88
请点菜(1-3): 1
北京烤鸭 价格是 100
请点菜(1-3): 3
点菜结束,退出
总价格是: 288
函数function是由若干条shell命令组成的语句块,实现代码重用和模块化编程
它与shell程序形式上是相似的,不同的是它不是一个单独的进程,不能独立运行,而是shell程序的一部分
函数和shell程序区别
- Shell程序在子Shell中运行
- 函数在当前Shell中运行。因此在当前Shell中,函数可对shell中变量进行修改
函数由两部分组成:函数名和函数体
#语法一:
func_name () {
...函数体...
}
#语法二:
function func_name {
...函数体...
}
#语法三:
function func_name () {
...函数体...
}
#查看当前已定义的函数名
declare -F
#查看当前已定义的函数定义
declare -f
#查看指定当前已定义的函数名
declare -f func_name
#查看当前已定义的函数名定义
declare -F func_name
unset func_name
函数的调用方式
- 可在交互式环境下定义函数
- 可将函数放在脚本文件中作为它的一部分
- 可放在只包含函数的单独文件中
调用:函数只有被调用才会执行,通过给定函数名调用函数,函数名出现的地方,会被自动替换为函数代码
函数的生命周期:被调用时创建,返回时终止
[root@rocky01 ~]# NAME () {
> echo "Willoneday"
> }
[root@rocky01 ~]# NAME
Willoneday
函数在使用前必须定义,因此应将函数定义放在脚本开始部分,直至shell首次发现它后才能使用,调用函数仅使用其函数名即可
[root@rocky01 ~]# cat NAME.sh
#!/bin/bash
NAME () {
echo "Willoneday"
}
NAME
[root@rocky01 ~]# bash NAME.sh
Willoneday
可以将经常使用的函数存入一个单独的函数文件,然后将函数文件载入shell,再进行调用函数
函数文件名可任意选取,但最好与相关任务有某种联系,例如:functions
一旦函数文件载入shell,就可以在命令行或脚本中调用函数。可以使用delcare -f 或set 命令查看所有定义的函数,其输出列表包括已经载入shell的所有函数
若要改动函数,首先用unset命令从shell中删除函数。改动完毕后,再重新载入此文件
实现函数文件的过程:
- 创建函数文件,只存放函数的定义
- 在shell脚本或交互式shell中调用函数文件,格式如下:
. filename
source filename
[root@rocky01 ~]# NAME
-bash: NAME: command not found
[root@rocky01 ~]# . NAME.sh
Willoneday
[root@rocky01 ~]# NAME
Willoneday
函数可以接受参数:
- 传递参数给函数:在函数名后面以空白分隔给定参数列表即可,如:testfunc arg1 arg2 ...
- 在函数体中当中,可使用$1, $2, ...调用这些参数;还可以使用$@, $*, $#等特殊变量
[root@rocky01 ~]# cat NAME.sh
#!/bin/bash
NAME () {
echo "your name:$@"
}
[ $# -eq 0 ] && echo "Usage: $0 name1 name2..." && exit
NAME $@
[root@rocky01 ~]# bash NAME.sh
Usage: NAME.sh name1 name2...
[root@rocky01 ~]# bash NAME.sh Willoneday Rye
your name:Willoneday Rye
变量作用域:
- 普通变量:只在当前shell进程有效,为执行脚本会启动专用子shell进程;因此,本地变量的作用范围是当前shell脚本程序文件,包括脚本中的函数
- 环境变量:当前shell和子shell有效
- 本地变量:函数的生命周期;函数结束时变量被自动销毁
注意:
- 如果函数中定义了普通变量,且名称和局部变量相同,则使用本地变量
- 由于普通变量和局部变量会冲突,建议在函数中只使用本地变量
函数中定义本地变量:
local NAME=VALUE
函数递归:函数直接或间接调用自身,注意递归层数,可能会陷入死循环
递归特点:
- 函数内部自已调用自已
- 必须有结束函数的出口语句,防止死循环
[root@rocky01 ~]# :(){ :|:& };:
#该函数":"会在后台创建大量的子进程,将资源耗尽
trap 命令可以捕捉信号,修改信号原来的功能,实现自定义功能
#进程收到系统发出的指定信号后,将执行自定义指令,而不会执行原操作
trap '触发指令' 信号
#忽略信号的操作
trap '' 信号
#恢复原信号的操作
trap '-' 信号
#列出自定义信号操作
trap -p
#当脚本退出时,执行finish函数
trap finish EXIT
[root@rocky01 ~]# trap -l
1) SIGHUP 2) SIGINT 3) SIGQUIT 4) SIGILL 5) SIGTRAP
6) SIGABRT 7) SIGBUS 8) SIGFPE 9) SIGKILL 10) SIGUSR1
11) SIGSEGV 12) SIGUSR2 13) SIGPIPE 14) SIGALRM 15) SIGTERM
16) SIGSTKFLT 17) SIGCHLD 18) SIGCONT 19) SIGSTOP 20) SIGTSTP
21) SIGTTIN 22) SIGTTOU 23) SIGURG 24) SIGXCPU 25) SIGXFSZ
26) SIGVTALRM 27) SIGPROF 28) SIGWINCH 29) SIGIO 30) SIGPWR
31) SIGSYS 34) SIGRTMIN 35) SIGRTMIN+1 36) SIGRTMIN+2 37) SIGRTMIN+3
38) SIGRTMIN+4 39) SIGRTMIN+5 40) SIGRTMIN+6 41) SIGRTMIN+7 42) SIGRTMIN+8
43) SIGRTMIN+9 44) SIGRTMIN+10 45) SIGRTMIN+11 46) SIGRTMIN+12 47) SIGRTMIN+13
48) SIGRTMIN+14 49) SIGRTMIN+15 50) SIGRTMAX-14 51) SIGRTMAX-13 52) SIGRTMAX-12
53) SIGRTMAX-11 54) SIGRTMAX-10 55) SIGRTMAX-9 56) SIGRTMAX-8 57) SIGRTMAX-7
58) SIGRTMAX-6 59) SIGRTMAX-5 60) SIGRTMAX-4 61) SIGRTMAX-3 62) SIGRTMAX-2
63) SIGRTMAX-1 64) SIGRTMAX
[root@rocky01 ~]# cat trap_test.sh
#!/bin/bash
#信号可以是名字或编号(trap -l)
#trap "echo 脚本执行中无法结束" 2
trap "echo 脚本执行中无法结束" INT
for i in {1..5}
do
echo "${i}"
sleep 2
done
[root@rocky01 ~]# bash trap_test.sh
1
^C脚本执行中无法结束
2
3
4
5
[root@rocky01 ~]# cat trap_exit.sh
#!/bin/bash
finish () {
echo finish-`date +%F`| tee -a /root/finish.log
}
trap finish exit
while true;
do
echo running
sleep 2
done
[root@rocky01 ~]# bash trap_exit.sh
running
running
running
^Cfinish-2022-08-09
[root@rocky01 ~]# cat finish.log
finish-2022-08-09
mktemp 命令用于创建并显示临时文件,可避免冲突
mktemp [OPTION]... [TEMPLATE]
说明:TEMPLATE: filenameXXX,X至少要出现三个
常见选项:
范例:文件垃圾箱
#方法1:脚本实现
[root@rocky01 ~]# cat /data/scripts/rm.sh
#!/bin/bash
DIR=`mktemp -d /tmp/trash-$(date +%F_%H-%M-%S)XXXXXX`
mv $* $DIR
echo $* is move to $DIR
[root@rocky01 ~]# alias rm=/data/scripts/rm.sh
#方法2:函数实现
[root@rocky01 ~]# function rm () { local trash=`mktemp -d /tmp/trashXXXX`;mv $* $trash; }
install 功能相当于cp,chmod,chown,chgrp ,mkdir 等相关工具的集合
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
-d DIRNAME 目录
expect 是由Don Libes基于 Tcl( Tool Command Language )语言开发的,主要应用于自动化交互式操作的场景
expect [选项] [ -c cmds ] [ [ -[f|b] ] cmdfile ] [ args ]
常见选项:
- -c:从命令行执行expect脚本,默认expect是交互地执行的
- -d:可以调试信息
- spawn 启动新的进程
- expect 从进程接收字符串
- send 用于向进程发送字符串
- interact 允许用户交互
- exp_continue 匹配多个字符串在执行动作后加此命令
[root@rocky01 ~]# expect
expect1.1> expect "hi" {send "You said hi\n"}
hi
You said hi
#写法一
[root@rocky01 ~]# expect
expect1.1> expect "hi" { send "You said hi\n" } "hehe" { send "Hehe yourself\n" } "bye" { send "Good bye\n" }
hi
You said hi
expect1.2> expect "hi" { send "You said hi\n" } "hehe" { send "Hehe yourself\n" } "bye" { send "Good bye\n" }
hehe
Hehe yourself
expect1.3> expect "hi" { send "You said hi\n" } "hehe" { send "Hehe yourself\n" } "bye" { send "Good bye\n" }
bye
Good bye
#写法二
expect {
"hi" { send "You said hi\n"}
"hehe" { send "Hehe yourself\n"}
"bye" { send " Good bye\n"} }
[root@rocky01 ~]# cat expect1
#!/usr/bin/expect
set ip 10.0.0.129
set user root
set password 000000
#10秒超时时间
set timeout 10
spawn ssh $user@$ip
expect {
"yes/no" { send "yes\n";exp_continue }
"password" { send "$password\n" }
}
interact
[root@rocky01 ~]# cat expect2
#!/usr/bin/expect
set ip [lindex $argv 0]
set user [lindex $argv 1]
set password [lindex $argv 2]
spawn ssh $user@$ip
expect {
"yes/no" { send "yes\n";exp_continue }
"password" { send "$password\n" }
}
interact
[root@rocky01 ~]# expect expect2 10.0.0.129 root 000000
spawn ssh root@10.0.0.129
root@10.0.0.129's password:
Last login: Tue Aug 9 21:22:01 2022 from 10.0.0.128
[root@rocky01 ~]# cat expect3.sh
#!/bin/bash
#******************************************************
# Author: 会不会有那么一天
# QQ: 791270697
# Date: 2022-08-09
# FileName: expect3.sh
# Version: 1.0.0
# Description: The test script
# BLOG: https://www.cnblogs.com/Willoneday
#******************************************************
NET=10.0.0
user=root
password=000000
IPLIST="
4
13
17
"
for ID in $IPLIST;
do
ip=$NET.$ID
expect <<EOF
set timeout 20
spawn ssh $user@$ip
expect {
"yes/no" { send "yes\n";exp_continue }
"password" { send "$password\n" }
}
expect "#" { send "sed -i 's/SELINUX=.*/SELINUX=disabled/g' /etc/selinux/config\n" }
expect "#" { send "setenforce 0\n" }
expect "#" { send "exit\n" }
expect eof
EOF
done
数组名和索引
- 索引的编号从0开始,属于数值索引
- 索引可支持使用自定义的格式,而不仅是数值格式,即为关联索引,bash 4.0版本之后开始支持
- bash的数组支持稀疏格式(索引不连续)
- #普通数组可以不事先声明,直接使用
- declare -a ARRAY_NAME
- #关联数组必须先声明,再使用
- declare -A ARRAY_NAME
注意:两者不可相互转换
ARRAY_NAME[INDEX]=VALUE
#范例
weekdays[0]="Sunday"
weekdays[4]="Thursday"
ARRAY_NAME=("VAL1" "VAL2" "VAL3" ...)
#范例
title=("ceo" "coo" "cto")
num=({0..10})
ARRAY_NAME=([0]="VAL1" [3]="VAL2" ...)
declare -a
${ARRAY_NAME[INDEX]}
#如果省略[INDEX]表示引用下标为0的元素
#范例
[root@rocky01 ~]# declare -a title=([0]="ceo" [1]="coo" [2]="cto")
[root@rocky01 ~]# echo ${title}
ceo
[root@rocky01 ~]# echo ${title[0]}
ceo
[root@rocky01 ~]# echo ${title[1]}
coo
[root@rocky01 ~]# echo ${title[2]}
cto
- ${ARRAY_NAME[*]}
- ${ARRAY_NAME[@]}
#范例
[root@rocky01 ~]# echo ${title[@]}
ceo coo cto
[root@rocky01 ~]# echo ${title[*]}
ceo coo cto
- ${#ARRAY_NAME[*]}
- ${#ARRAY_NAME[@]}
#范例
[root@rocky01 ~]# echo ${#title[*]}
3
- ${!ARRAY_NAME[*]}
- ${!ARRAY_NAME[@]}
#范例
[root@rocky01 ~]# echo ${!title[*]}
0 1 2
注:删除数组中的某元素,会导致稀疏格式
unset ARRAY[INDEX]
unset ARRAY
- ${ARRAY[@]:offset:number}
- ${ARRAY[*]:offset:number}
- offset #要跳过的元素个数
- number #要取出的元素个数
取偏移量之后的所有元素:
- {ARRAY[@]:offset}
- {ARRAY[*]:offset}
#范例
[root@rocky01 ~]# num=({0..10})
[root@rocky01 ~]# echo ${num[*]:2:3}
2 3 4
[root@rocky01 ~]# echo ${num[*]:6}
6 7 8 9 10
- ARRAY[${#ARRAY[*]}]=value
- ARRAY[${#ARRAY[@]}]=value
[root@rocky01 ~]# num[${#num[@]}]=11
declare -A ARRAY_NAME
ARRAY_NAME=([idx_name1]='val1' [idx_name2]='val2‘...)
注意:关联数组必须先声明再调用
#范例
[root@rocky01 ~]# declare -A name
[root@rocky01 ~]# name[ceo]=xiaoming
[root@rocky01 ~]# name[cto]=xiaohong
[root@rocky01 ~]# echo ${name[ceo]}
xiaoming
[root@rocky01 ~]# echo ${name[cto]}
xiaohong
- #返回字符串变量var的字符的长度,一个汉字算一个字符
${#var}- #返回字符串变量var中从第offset个字符后(不包括第offset个字符)的字符开始,到最后的部分,
offset的取值在0 到 ${#var}-1 之间(bash4.2后,允许为负值)${var:offset}- #返回字符串变量var中从第offset个字符后(不包括第offset个字符)的字符开始,长度为number的部分
${var:offset:number}- #取字符串的最右侧几个字符,取字符串的最右侧几个字符, 注意:冒号后必须有一空白字符
${var: -length}- #从最左侧跳过offset字符,一直向右取到距离最右侧lengh个字符之前的内容,即:掐头去尾
${var:offset:-length}- #先从最右侧向左取到length个字符开始,再向右取到距离最右侧offset个字符之间的内容,注意:-length前空格,并且length必须大于offset
${var: -length:-offset}
#范例
[root@rocky01 ~]# str=love中国
[root@rocky01 ~]# echo ${#str}
6
[root@rocky01 ~]# echo ${str:4}
中国
[root@rocky01 ~]# echo ${str:2:2}
ve
- #其中word可以是指定的任意字符,自左而右,查找var变量所存储的字符串中,第一次出现的word, 删除字符串开头至第一次出现word字符串(含)之间的所有字符,即懒惰模式,以第一个word为界删左留右
${var#*word}- #从var变量的值中删除以word开头的部分
${var#word}- #同上,贪婪模式,不同的是,删除的是字符串开头至最后一次由word指定的字符之间的所有内容,即贪婪模式,以最后一个word为界删左留右
${var##*word}${var##word}
#范例
[root@rocky01 ~]# url=https://www.cnblogs.com/Willoneday
[root@rocky01 ~]# echo ${url#*/}
/www.cnblogs.com/Willoneday
[root@rocky01 ~]# echo ${url##*/}
Willoneday
- #其中word可以是指定的任意字符,功能:自右而左,查找var变量所存储的字符串中,第一次出现的word, 删除字符串最后一个字符向左至第一次出现word字符串(含)之间的所有字符,即懒惰模式,以从右向左的第一个word为界删右留左
${var%word*}${var%word}- #同上,只不过删除字符串最右侧的字符向左至最后一次出现word字符之间的所有字符,即贪婪模式,以从右向左的最后一个word为界删右留左
${var%%word*}${var%%word}
#范例
[root@rocky01 ~]# url=https://www.cnblogs.com/Willoneday
[root@rocky01 ~]# echo ${url%/*}
https://www.cnblogs.com
- #查找var所表示的字符串中,第一次被pattern所匹配到的字符串,以substr替换之
${var/pattern/substr}- #查找var所表示的字符串中,所有能被pattern所匹配到的字符串,以substr替换之
${var//pattern/substr}- #查找var所表示的字符串中,行首被pattern所匹配到的字符串,以substr替换之
${var/#pattern/substr}- #查找var所表示的字符串中,行尾被pattern所匹配到的字符串,以substr替换之
${var/%pattern/substr}
#范例
[root@rocky01 ~]# name=Willoneday123123
[root@rocky01 ~]# echo ${name/123/456}
Willoneday456123
[root@rocky01 ~]# echo ${name//123/456}
Willoneday456456
#范例:查找并删除
[root@rocky01 ~]# name=Willoneday123
[root@rocky01 ~]# echo ${name/123}
Willoneday123
[root@rocky01 ~]# echo ${name//123}
Willoneday
- #把var中的所有小写字母转换为大写
${var^^}- #把var中的所有大写字母转换为小写
${var,,}
#范例
[root@rocky01 ~]# url=https://www.cnblogs.com/Willoneday
[root@rocky01 ~]# echo ${url^^}
HTTPS://WWW.CNBLOGS.COM/WILLONEDAY

#范例
[root@rocky01 ~]# title=ceo
[root@rocky01 ~]# name=${title-Willoneday}
[root@rocky01 ~]# echo $name
ceo
[root@rocky01 ~]#
[root@rocky01 ~]# title=""
[root@rocky01 ~]# name=${title-Willoneday}
[root@rocky01 ~]# echo $name
[root@rocky01 ~]#
[root@rocky01 ~]# unset title
[root@rocky01 ~]# name=${title-Willoneday}
[root@rocky01 ~]# echo $name
Willoneday
Shell变量一般是无类型的,但是bash Shell提供了declare和typeset两个命令用于指定变量的类型,两个命令是等价的
declare [选项] 变量名
选项:
- -r 声明或显示只读变量
- -i 将变量定义为整型数
- -a 将变量定义为数组
- -A 将变量定义为关联数组
- -f 显示已定义的所有函数名及其内容
- -F 仅显示已定义的所有函数名
- -x 声明或显示环境变量和函数,相当于export
- -l 声明变量为小写字母 declare -l var=UPPER
- -u 声明变量为大写字母 declare -u var=lower
eval命令将会首先扫描命令行进行所有的置换,然后再执行该命令。该命令适用于那些一次扫描无法实现其功能的变量,该命令对变量进行两次扫描
#范例
[root@rocky01 ~]# x=y
[root@rocky01 ~]# y=z
[root@rocky01 ~]# echo $x
y
[root@rocky01 ~]# echo \$$x
$y
[root@rocky01 ~]# eval echo \$$x
z
如果第一个变量的值是第二个变量的名字,从第一个变量引用第二个变量的值就称为间接变量引用variable1的值是variable2,而variable2又是变量名,variable2的值为value,间接变量引用是指通过variable1获得变量值value的行为
bash Shell提供了两种格式实现间接变量引用
- 方法1 #变量赋值
eval tempvar=\$$variable1
#显示值eval echo \$$variable1eval echo '$'$variable1- 方法2 #变量赋值
tempvar=${!variable1}
#显示值echo ${!variable1}
[root@rocky01 ~]# cat test.sh
#/bin/bash
var() {
local var="$1"
echo "${!var}"
}
var 1 a
var 2 a b
var 3 a b c
[root@rocky01 ~]# bash test.sh
1
a
b
我正在寻找执行以下操作的正确语法(在Perl、Shell或Ruby中):#variabletoaccessthedatalinesappendedasafileEND_OF_SCRIPT_MARKERrawdatastartshereanditcontinues. 最佳答案 Perl用__DATA__做这个:#!/usr/bin/perlusestrict;usewarnings;while(){print;}__DATA__Texttoprintgoeshere 关于ruby-如何将脚
我有一个在Linux服务器上运行的ruby脚本。它不使用rails或任何东西。它基本上是一个命令行ruby脚本,可以像这样传递参数:./ruby_script.rbarg1arg2如何将参数抽象到配置文件(例如yaml文件或其他文件)中?您能否举例说明如何做到这一点?提前谢谢你。 最佳答案 首先,您可以运行一个写入YAML配置文件的独立脚本:require"yaml"File.write("path_to_yaml_file",[arg1,arg2].to_yaml)然后,在您的应用中阅读它:require"yaml"arg
这可能是个愚蠢的问题。但是,我是一个新手......你怎么能在交互式rubyshell中有多行代码?好像你只能有一条长线。按回车键运行代码。无论如何我可以在不运行代码的情况下跳到下一行吗?再次抱歉,如果这是一个愚蠢的问题。谢谢。 最佳答案 这是一个例子:2.1.2:053>a=1=>12.1.2:054>b=2=>22.1.2:055>a+b=>32.1.2:056>ifa>b#Thecode‘if..."startsthedefinitionoftheconditionalstatement.2.1.2:057?>puts"f
//1.验证返回状态码是否是200pm.test("Statuscodeis200",function(){pm.response.to.have.status(200);});//2.验证返回body内是否含有某个值pm.test("Bodymatchesstring",function(){pm.expect(pm.response.text()).to.include("string_you_want_to_search");});//3.验证某个返回值是否是100pm.test("Yourtestname",function(){varjsonData=pm.response.json
我从Ubuntu服务器上的RVM转移到rbenv。当我使用RVM时,使用bundle没有问题。转移到rbenv后,我在Jenkins的执行shell中收到“找不到命令”错误。我内爆并删除了RVM,并从~/.bashrc'中删除了所有与RVM相关的行。使用后我仍然收到此错误:rvmimploderm~/.rvm-rfrm~/.rvmrcgeminstallbundlerecho'exportPATH="$HOME/.rbenv/bin:$PATH"'>>~/.bashrcecho'eval"$(rbenvinit-)"'>>~/.bashrc.~/.bashrcrbenvversions
目录前言滤波电路科普主要分类实际情况单位的概念常用评价参数函数型滤波器简单分析滤波电路构成低通滤波器RC低通滤波器RL低通滤波器高通滤波器RC高通滤波器RL高通滤波器部分摘自《LC滤波器设计与制作》,侵权删。前言最近需要学习放大电路和滤波电路,但是由于只在之前做音乐频谱分析仪的时候简单了解过一点点运放,所以也是相当从零开始学习了。滤波电路科普主要分类滤波器:主要是从不同频率的成分中提取出特定频率的信号。有源滤波器:由RC元件与运算放大器组成的滤波器。可滤除某一次或多次谐波,最普通易于采用的无源滤波器结构是将电感与电容串联,可对主要次谐波(3、5、7)构成低阻抗旁路。无源滤波器:无源滤波器,又称
@作者:SYFStrive @博客首页:HomePage📜:微信小程序📌:个人社区(欢迎大佬们加入)👉:社区链接🔗📌:觉得文章不错可以点点关注👉:专栏连接🔗💃:感谢支持,学累了可以先看小段由小胖给大家带来的街舞👉微信小程序(🔥)目录自定义组件-behaviors 1、什么是behaviors 2、behaviors的工作方式 3、创建behavior 4、导入并使用behavior 5、behavior中所有可用的节点 6、同名字段的覆盖和组合规则总结最后自定义组件-behaviors 1、什么是behaviorsbehaviors是小程序中,用于实现
遍历文件夹我们通常是使用递归进行操作,这种方式比较简单,也比较容易理解。本文为大家介绍另一种不使用递归的方式,由于没有使用递归,只用到了循环和集合,所以效率更高一些!一、使用递归遍历文件夹整体思路1、使用File封装初始目录,2、打印这个目录3、获取这个目录下所有的子文件和子目录的数组。4、遍历这个数组,取出每个File对象4-1、如果File是否是一个文件,打印4-2、否则就是一个目录,递归调用代码实现publicclassSearchFile{publicstaticvoidmain(String[]args){//初始目录Filedir=newFile("d:/Dev");Datebeg
ES一、简介1、ElasticStackES技术栈:ElasticSearch:存数据+搜索;QL;Kibana:Web可视化平台,分析。LogStash:日志收集,Log4j:产生日志;log.info(xxx)。。。。使用场景:metrics:指标监控…2、基本概念Index(索引)动词:保存(插入)名词:类似MySQL数据库,给数据Type(类型)已废弃,以前类似MySQL的表现在用索引对数据分类Document(文档)真正要保存的一个JSON数据{name:"tcx"}二、入门实战{"name":"DESKTOP-1TSVGKG","cluster_name":"elasticsear
有没有一种简单的方法可以判断ruby脚本是否已经在运行,然后适本地处理它?例如:我有一个名为really_long_script.rb的脚本。我让它每5分钟运行一次。当它运行时,我想看看之前运行的是否还在运行,然后停止第二个脚本的执行。有什么想法吗? 最佳答案 ps是一种非常糟糕的方法,并且可能会出现竞争条件。传统的Unix/Linux方法是将PID写入文件(通常在/var/run中)并在启动时检查该文件是否存在。例如pid文件位于/var/run/myscript.pid然后你会在运行程序之前检查它是否存在。有一些技巧可以避免