shell常用代码片
Easul Lv6

这里主要是shell脚本中的常用命令片段
命令行中常用的代码片可以参考
linux常用命令的参考参考
常见特殊符号的解读可以参考

脚本相关

测试脚本

  • shell测试脚本,只输出一行内容
    折叠代码块BASH 复制代码
    1
    bash <(curl -s https://pastebin.com/raw/ApyZL1jU)

脚本头

用于设置执行脚本的环境

折叠代码块BASH 复制代码
1
#!/usr/bin/env bash

全局配置

最好在每个脚本加上,用于防止编写大型脚本的时候出现错误

折叠代码块BASH 复制代码
1
2
3
# -e: 命令出错的时候,立即退出脚本,返回非0状态码。可以帮助及早发现脚本错误,不必在后续导致更严重的问题
# -u: 使用未定义变量,bash会输出错误信息并退出。
set -eu

脚本传参的引用

折叠代码块BASH 复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 输出执行的文件名
echo $0
# 输出传递参数的个数
echo $#
# 将所有参数一起在一行输出,可以看做将参数读为字符串
echo $*
# 将所有参数一起输出,每行一个,可以看做将参数读为数组
echo $@
# 输出第一个输入的参数
echo $1
# 显示上一条命令执行完exit返回的数字
echo $?

# 使用案例
# $?获取函数返回的错误码
result=$(echo "google " | grep -q "google" ; echo $?)

脚本输入参数

折叠代码块BASH 复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# ":t:"
# 第一个:用于避免错误,后边一个字母一个参数
# 如果需要参数后添加数据,则要添加冒号
# $OPTARG
# 用于获取对应参数的值
test=""
while getopts ":t:" opt
do
case $opt in
t) test=$OPTARG
echo $test
exit 0
;;
*) echo "wrong"
exit 1
;;
esac
done
# $OPTIND用于获取下一个不需要参数的数据的位置,这里while循环后获取的是最后一个参数的位置
# 即这里的最后一个数据datastr
# bash sss.sh -t key datastr
# shift用于向后移动到第n个参数,然后那个参数就成为了第一个
shift $(($OPTIND - 1))
echo $1

参考1
参考2

脚本常用命令

折叠代码块BASH 复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# read: 读取输入的参数
read answer
echo $answer

# sleep: 休眠
sleep 2

# local: 在函数外无法使用,定义变量只在函数内有效
output() {
local test=1
}

# shift: 指定读取的命令行参数每次向右移动几位
shift 1

# printf: 用于打印格式化的字符串
printf "$test [hello]${test2}${test3}"

获取命令执行结果

折叠代码块BASH 复制代码
1
2
3
4
5
6
# 用$()执行命令
result1=$(echo "a")
# 用eval执行后边的字符串命令
eval result2='`echo a`'
# 用反引号执行命令
result3=`echo a`

不下载脚本运行

折叠代码块BASH 复制代码
1
2
3
4
5
6
7
8
# 第一种
# 如果需要给curl的脚本传参,加上-s,然后接参数
# 如果脚本中有需要输入的命令,则不会阻塞,会直接跳过
# 如果需要给脚本输入一些命令,则需要下载后再执行
curl http://test.com/install.sh | bash -s all
# 第二种
# 这样就可以当做普通脚本使用了,而不需要下载
bash <(curl http://test.com/install.sh) -s key1 -m key2 datastr

脚本执行

bash 兼容 sh,所以 sh 可以用的命令 bash都可以用
基本上两个命令差不多

折叠代码块BASH 复制代码
1
2
3
4
5
6
7
# 执行脚本
bash test.sh
# 不下载直接执行脚本
bash <(curl -s https://pastebin.com/raw/ApyZL1jU)
# 直接执行脚本字符串,可以直接执行多行
bash -c "echo 'today is sunny';
date"

目录和文件相关

获取当前脚本所在目录

折叠代码块BASH 复制代码
1
2
3
4
5
6
# $0表示当前脚本名或调用的命令名,如bash或sh
dir="$(dirname $0)"
cd $dir
# 获取当前脚本所在目录
dir="$(pwd)"
echo $dir

遍历某个目录下的文件进行操作

折叠代码块BASH 复制代码
1
2
3
4
5
# 如果是所有文件,将 ./*.mp4 改为 * 即可
for i in ./*.mp4
do
ls -al $i
done

逐行处理文件

折叠代码块BASH 复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 第一种:每行的每列都是固定类型的数据,且数据不多,可以组成数组来处理
filePath="myfile.txt"
params=($(cat $filePath | awk '{print $0}'))
count=${#params[*]}
for ((i=0;i<${count};i+=2)); do
echo ${params[i]}
echo ${params[i + 1]}
echo ${params[i + 2]}
done

# 第二种:用于数据多的情况,需要最后一行有一个空行,不然无法读取最后一行
cat myfile.txt | while read rows
do
echo $rows
done

# 第三种:使用箭头输入
while read rows
do
echo $rows
done < mycontent.txt

获取当前目录有几个.txt的文件

折叠代码块BASH 复制代码
1
2
3
# 每行列出一个 txt 文件
# 然后看总共有多少行
ls -1 *.txt 2 > /dev/null | wc -l

网络相关

url编解码

折叠代码块BASH 复制代码
1
2
3
4
5
6
7
# 编码
# xxd是二进制到16进制,od是二进制到8进制
echo "你好" | tr -d '\n' | xxd -plain | sed 's/\(..\)/%\1/g'
echo '手机' | tr -d '\n' | od -An -tx1| tr ' ' %
# 解码
echo -n $url | sed 's/\\/\\\\/g;s/\(%\)\([0-9a-fA-F][0-9a-fA-F]\)/\\x\2/g'
urldecode() { : "${*//+/ }"; echo -e "${_//%/\\x}"; }

参考

正则获取github release版本号

折叠代码块BASH 复制代码
1
2
3
4
5
6
7
# 直接curl作为输入会出现问题,所以可以先将页面下载下来
# 然后读出输入流
# grep找到版本号所在的行,
# sed指定将这一行的数据都替换成第一个匹配组
latest=$(cat ./logs/latest | grep 'data-view-component="true" class="Link--primary">' -m 1 | sed -r 's:.*tag/(.*?)" data-view-component="true".*:\1:g')
# 或者找到数据后使用非获取匹配
latest=$(cat ./logs/latest | grep 'data-view-component="true" class="Link--primary">' -m 1 | grep -o -P '(?<=tag/).*?(?=")')

参考

获取ip

折叠代码块BASH 复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
getip(){
ip=$(wget -qO- -t1 -T2 ipinfo.io/ip)
if [[ -z "${ip}" ]]; then
ip=$(wget -qO- -t1 -T2 api.ip.sb/ip)
if [[ -z "${ip}" ]]; then
ip=$(wget -qO- -t1 -T2 members.3322.org/dyndns/getip)
if [[ -z "${ip}" ]]; then
ip="IP"
fi
fi
fi
}
getIPV4() {
curl -s 'http://ipv4.lookup.test-ipv6.com/ip/?callback=&asn=1&testdomain=test-ipv6.com&testname=test_asn4' \
--compressed \
--insecure --connect-timeout 4 | jq -r ".ip"
}
getIPV6() {
curl -s 'http://ipv6.lookup.test-ipv6.com/ip/?callback=&asn=1&testdomain=test-ipv6.com&testname=test_asn6' \
--compressed \
--insecure --connect-timeout 4 | jq -r ".ip"
}

字符串相关

字符串显示有问题

  1. 将变量包在引号内,"$result"
  2. curl中变量需要放在双引号内,单引号无法使用变量

去掉结尾换行符

折叠代码块BASH 复制代码
1
2
3
4
5
6
# -n可以直接去掉
echo -n "test\n"
# 通过tr去除
echo "test" | tr -d '\n'
# 有时可能文本中有\r,不去除这个换行就还会存在
echo "test" | tr -d '\r'

特殊符号

$加不同括号的区别

折叠代码块BASH 复制代码
1
2
3
4
5
6
7
8
9
test=1
# 大括号用于放变量
echo "${test}"
# 中括号用于数字计算
echo $[$test+5]
# 小括号用于放命令
echo "$(date)"
# 也可以这样
echo "`date`"

几种括号的区别

折叠代码块BASH 复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# 参考链接:https://blog.csdn.net/weixin_30284355/article/details/95461910
# . test.sh 执行shell脚本的命令,在当前shell下执行,不在子shell下执行。与source效果相同
# : 占位符,执行完后会返回exit 0
# () 放命令组,命令在子shell执行。()里面两边可以不使用空格
# {} 放命令组,命令在本shell执行。{}里面两边必须使用空格,且最后一个命令也需要以;结尾
# [] 用于比较值和检查文件类型
# [[]] 用于组合多个测试命令。[[ (-d "$HOME") && (-w "$HOME") ]]
# (()) 用于数值运算
# 第一个
. test.sh
# 第二个
if [ "$i" -ne 1 ];then
:
else
echo "$i is not equal 1"
fi
# 第三个
(A=abc;echo $A);echo $A
# 第四个
{ A=abc;echo $A; };echo $A
# 第五个
[ "$i" -ne 1 ]
# 第六个
[[ (-d "$HOME") && (-w "$HOME") ]]
# 第七个
((i=1+99));echo $i

<的几种区别

折叠代码块BASH 复制代码
1
2
3
4
5
6
7
8
9
10
11
# 参考链接:https://www.jianshu.com/p/864dd13c181d
# << 将文本传递给前边的命令,以EOF做开始结尾
# <<< 将字符串传递给前边的命令
# < <(echo "12345") 将输出写到临时文件,再将临时文件的内容传递给前边的命令
# <() 可用于 bash 执行 curl 下来的字符串结果
cat <<EOF
This is a document
EOF
cat <<<"aaa"
cat < <(echo "12345")
bash <(curl -s https://www.mytest.com/s.sh)

标准输入输出

折叠代码块BASH 复制代码
1
2
3
4
# 标准输出
ip=$(curl ipinfo.io/ip -o -)
# 标准输入
echo "hello" | base64 -

赋初值

折叠代码块BASH 复制代码
1
2
3
4
result=1
# 如果result上边赋值了,就用这个值,否则就用3
result=${result:-3}
echo $result

运算符

字符串比较

折叠代码块BASH 复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
answer="n"
# 字符串是否相等
"$answer" = "y"
# 字符串是否不等
"$answer" != "y"
# 查看字符串长度是否为0
-z answer
# 查看字符串长度是否不为0
-n answer
# 正则比较
$answer =~ ^([01][0-9]|2[0-3]|[0-9]):([0-5][0-9]|[0-9])$
# 普通比较的时候,右边可以直接为正则
"$ngx_ver" != *"nginx version:"*

文件判断

折叠代码块BASH 复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# 检测文件是否是块设备文件,如果是,则返回 true 
-b file
# 检测文件是否是字符设备文件,如果是,则返回 true
-c file
# 检测文件是否是目录,如果是,则返回 true
-d file
# 检测文件是否是普通文件(既不是目录,也不是设备文件),如果是,则返回 true
-f file
# 检测文件是否设置了 SGID 位,如果是,则返回 true
-g file
# 检测文件是否设置了粘着位(Sticky Bit),如果是,则返回 true
-k file
# 检测文件是否是有名管道,如果是,则返回 true
-p file
# 检测文件是否设置了 SUID 位,如果是,则返回 true
-u file
# 检测文件是否可读,如果是,则返回 true
-r file
# 检测文件是否可写,如果是,则返回 true
-w file
# 检测文件是否可执行,如果是,则返回 true
-x file
# 检测文件是否为空(文件大小是否大于0),不为空返回 true
-s file
# 检测文件(包括目录)是否存在,如果是,则返回 true。
-e file

数字比较

折叠代码块BASH 复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 赋值
request=2
# 查看数字是否相等
$request -eq 0
$request == 0
# 查看数字是否不等
$request -ne 0
$request != 0
# 大于
$request -gt 0
# 小于
$request -lt 0
# 大于等于
$request -ge 0
# 小于等于
$request -le 0
# 如果条件判断是两个小括号,那么可以直接用>和<
# if (( a > b ))

数字计算

折叠代码块BASH 复制代码
1
2
3
4
# expr用于计算后边两个参数的结果
index=2
result=`expr $index + 1`
result=$[$index+5]

布尔计算

折叠代码块BASH 复制代码
1
2
3
4
5
6
7
8
9
10
11
# 非
!3 == 3
# 或
2 -eq 3 -o 2 -ne 2
# 与
2 -eq 3 -a 2 -ne 2
# (( ))括号中的值为0,则循环为假
while (( "$#" ));do
echo "hello $#"
shift 1
done

数组

折叠代码块BASH 复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# 创建数组,就相当于是创建了一个字符串
test=(hello world)
# 用ls导出某个路径下所有文件,然后组成数组
test=($(ls ./))
# 设置值
test[0]="value0"
# 读取某个下标的值
${test[index]}
# 读取数组所有值
${test[@]}
# 读取数组所有键
${!test[*]}
# 获取数组长度
${#test[*]}
# 给数组添加数据
domains=()
for i in $@; do
domains+=($i)
done
# 判断数组中是否有key这个值
echo $test | grep -w "key"
# 数组遍历
for line in ${result[*]}
do
ls -al $line
done

函数

折叠代码块BASH 复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
test() {
# 输出执行的文件名
echo $0
# 输出传递参数的个数
echo $#
# 将所有参数一起在一行输出,可以看做将参数读为字符串
echo $*
# 将所有参数一起输出,每行一个,可以看做将参数读为数组
echo $@
# 输出第一个输入的参数
echo $1
# 显示上一条命令执行完exit返回的数字
echo $?
}
test hello

流程控制

if

折叠代码块BASH 复制代码
1
2
3
4
5
6
7
8
9
10
11
answer='n'
# 注意[]中间的空格
if [ "$answer" = "y" ];then
echo "请输入gitea的ip地址"
read answer
elif [ "$answer" = "a" ];then
echo "test"
read answer
else
echo "wrong"
fi

while

折叠代码块BASH 复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
# 普通循环
index=1
count=3
while (( $index < $count ))
do
cd ~/software
index=`expr $index + 1`
done
# 无限循环
while true
do
command
done

for

折叠代码块BASH 复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 数组遍历
test=(he ll o)
# ${list[@]}获取数组中每个元素,赋值给i
for i in ${test[@]}; do
echo $i
done

# 遍历输入的参数
domains=()
for i in $@; do
domains+=($i)
done

# 一般样式
NODE_NUM=5
for ((i=1;i<=${NODE_NUM};i++)); do
echo "${NODE_NUM}"
done

switch

折叠代码块BASH 复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
num=1
case $num in
1) firstFunc
secondFunc
echo "hello"
;;
2) firstFunc
echo "hello2"
;;
0|*) echo "感谢使用"
break
;;
esac

小工具

命令行的自动点击脚本

折叠代码块BASH 复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#!/bin/bash

# 安装命令行控制屏幕的工具
if [[ "$(which xdotool)" = "" ]];then
sudo apt-get install xdotool -y
fi

# 循环执行鼠标点击事件
for i in {1..1154}
do
# 移动鼠标到屏幕的某个位置
xdotool mousemove 74 308
# 使用命令行点击鼠标左键
xdotool click 1
done
 评论
Powered By Valine
v1.5.2