0x00 前言
本文汇总下笔者常用的Bash指令备份
0x01 BASH
1、批量查找文件内容
主要使用grep -rl
,如下面指令,查询当前目录下所有出现yyyy
字符串的文件列表:
grep yyyy -rl --include="*.txt" ./
2、批量替换文件内容
常用sed
搭配grep
指令使用,如下面指令,将当前目录./
下的所有.txt
文件中的yyyy
字符串替换为xxxx
sed -i s/yyyy/xxxx/g `grep yyyy -rl --include="*.txt" ./`
sed -i s/" CORE"/" SPECCORE"/g `grep " CORE" -rl --include="*.h" ./`
sed -i s/"aaaa"/"bbbb"/g `grep "bbbb" -rl --include="*.go" ./`
3、批量kill进程
ps aux|grep nginx|grep -v grep|awk '{print $2}'|xargs kill -9
4、仅替换当前目录下的文件内容
sed -i s/xxxx/yyyy/g ./*.txt
5、在匹配行的位置上面或者下面添加指定内容、删除指定行内容
注意下面sed
指令替换那列的a
和i
这两个参数:
sed -i /xxxx/d ./*.txt #删除命中查询条件的行
sed -i /7777/a77777 ./*.txt #在命中查询条件的下一行添加77777
sed -i /7777/i77777 ./*.txt #在命中查询条件的上一行添加77777
6、解析pcap抓包文件
下面示例,通过tcpdump -r
指令对抓包中的源IP进行TOP统计,并按照数量进行排序
tcpdump -r xxxx.pcap |awk '{print $3}'|awk -F '\.' '{print $1"."$2"."$3"."$4}' |sort |uniq -c |sort -nr -k 1
7、获取字符串最后一个字符
STR=123456abc
FINAL=`echo ${STR: -1}`
FINAL_O=${STR: -1} #与上面等价
FINAL2=`echo ${STR: -2}` #获取最后两个字符
8、去掉字符串最后两个字符
var="12345467,"
echo ${var%??}
9、去掉字符串末尾一个字符
var="12345467,"
echo ${var%?}
10、sed
如何处理ascii码为0
的字符?
find . -print0 | sed -e 's/\x0/\n/g'
在上例中,find
命令把当前目录下的文件名输出出来,以0
字符分隔。输出被管道送给sed
进行处理。在sed
中,则把0
字符替换成回车符
11、sed
如何使用shell中的变量
如何在sed
中使用shell定义的变量?要用双引号而不是单引号来引用sed命令,因为shell会处理双引号中的变量引用,而对单引号中的内容,shell完全不会处理
TERM1=term; TERM2=rxvt; echo "term" | sed -e "s/$TERM1/$TERM2/g"
0x02 字符串操作总结
12、字符串不对称分割
如何从指定字符(子字符串)开始截取?
1) 使用 #
号截取指定字符(或子字符串)右边字符
string="xx|xxxxx"
echo ${string#*|} #输出xxxxx
string="xx|123456"
echo ${string#*|123} #输出456
echo ${string#xx|123} #输出456
语法为:
${string#*chars}
其中,string
表示要截取的字符,chars
是指定的字符(或者子字符串),*
是通配符的一种,表示任意长度的字符串。*chars
连起使用的意思是:忽略左边的所有字符,直到遇见 chars
(chars
不会被截取)
2) 匹配到最后一个指定字符再结束,格式串为${string##*chars}
url="http://a.b.c/index.html"
echo ${url#*/} #输出/a.b.c/index.html
echo ${url##*/} #输出index.html
str="---aa+++aa@@@"
echo ${str#*aa} #结果为 +++aa@@@
echo ${str##*aa} #结果为 @@@
3) 使用 %
截取指定字符(或者子字符串)左边字符,格式为${string%chars*}
,注意*
的位置
url="http://a.b.c/index.html"
echo ${url%/*} #http://a.b.c
echo ${url%%/*} #结果为 http:
str="---aa+++aa@@@"
echo ${str%aa*} #结果为 ---aa+++
echo ${str%%aa*} #结果为 ---
汇总下:
匹配格式 | 说明 |
---|---|
${string: start :length} | 从 string 字符串的左边第 start 个字符开始,向右截取 length 个字符 |
${string: start} | 从 string 字符串的左边第 start 个字符开始截取,直到最后 |
${string: 0-start :length} | 从 string 字符串的右边第 start 个字符开始,向右截取 length 个字符 |
${string: 0-start} | 从 string 字符串的右边第 start 个字符开始截取,直到最后 |
${string#*chars} | 从 string 字符串第一次出现 *chars 的位置开始,截取 *chars 右边的所有字符 |
${string##*chars} | 从 string 字符串最后一次出现 *chars 的位置开始,截取 *chars 右边的所有字符 |
${string%*chars} | 从 string 字符串第一次出现 *chars 的位置开始,截取 *chars 左边的所有字符 |
${string%%*chars} | 从 string 字符串最后一次出现 *chars 的位置开始,截取 *chars 左边的所有字符 |
13、分割字符串
IN="bla@some.com;john@home.com"
arrIN=(${IN//;/ })
echo ${arrIN[1]} # Output: john@home.com
IFS=';' read -ra ADDR <<< "$IN"
for i in "${ADDR[@]}"; do
echo "$i"
done
$ echo "bla@some.com;john@home.com" | cut -d ";" -f 1
bla@some.com
$ echo "bla@some.com;john@home.com" | cut -d ";" -f 2
john@home.com
14、Bash解析JSON
### 方法简要说明:
### 1. 是先查找一个字符串:带双引号的key。如果没找到,则直接返回defaultValue。
### 2. 查找最近的冒号,找到后认为值的部分开始了,直到在层数上等于0时找到这3个字符:,}]。
### 3. 如果有多个同名key,则依次全部打印(不论层级,只按出现顺序)
### @author lux feary
###
### 3 params: json, key, defaultValue
function getJsonValuesByAwk() {
awk -v json="$1" -v key="$2" -v defaultValue="$3" 'BEGIN{
foundKeyCount = 0
while (length(json) > 0) {
# pos = index(json, "\""key"\""); ## 这行更快一些,但是如果有value是字符串,且刚好与要查找的key相同,会被误认为是key而导致值获取错误
pos = match(json, "\""key"\"[ \\t]*?:[ \\t]*");
if (pos == 0) {if (foundKeyCount == 0) {print defaultValue;} exit 0;}
++foundKeyCount;
start = 0; stop = 0; layer = 0;
for (i = pos + length(key) + 1; i <= length(json); ++i) {
lastChar = substr(json, i - 1, 1)
currChar = substr(json, i, 1)
if (start <= 0) {
if (lastChar == ":") {
start = currChar == " " ? i + 1: i;
if (currChar == "{" || currChar == "[") {
layer = 1;
}
}
} else {
if (currChar == "{" || currChar == "[") {
++layer;
}
if (currChar == "}" || currChar == "]") {
--layer;
}
if ((currChar == "," || currChar == "}" || currChar == "]") && layer <= 0) {
stop = currChar == "," ? i : i + 1 + layer;
break;
}
}
}
if (start <= 0 || stop <= 0 || start > length(json) || stop > length(json) || start >= stop) {
if (foundKeyCount == 0) {print defaultValue;} exit 0;
} else {
print substr(json, start, stop - start);
}
json = substr(json, stop + 1, length(json) - stop)
}
}'
}
json='{"code":200,"msg":"success","data":{"orderNo":"test_order_no"}}'
getJsonValuesByAwk "$json" "code" "defaultValue"
getJsonValuesByAwk "$json" "data" "defaultValue"
getJsonValuesByAwk "$json" "orderNo" "defaultValue"
15、bash解析JSON
:使用工具
raw='{"name":"tenmao","age":10,"hobbies":["bar","foo"],"address":{"province":"gd","city":"sz"}}'
echo $raw | jq -r '.name'
echo $raw | jq -r '.hobbies'
echo $raw | jq -r '.hobbies[0]'
echo $raw | jq -r '.address.city'
16、清除字符串首尾的空格
STR=" A B CCC D "
echo "$STR" | grep -o "[^ ]\+\( \+[^ ]\+\)*"
17、find
#列举出当前目录所有大于800M的文件
find . -type f -size +800M
du -h --max-depth=1
du -hm --max-depth=2 | sort -n
du -hm --max-depth=2 | sort -nr | head -12
#搜索文件并打印修改日期
find ./ -type f -name "*dns*" -printf "%TY-%Tm-%Td %TH:%TM %p\n"
# find搭配 xargs
find ./ -name "*.go" |xargs ls -l
# find 搭配tar打包
find . -type f -name "*.jpg" -print | xargs tar -czvf images.tar.gz
18、netstat
or ss
在现网中建议使用ss
命令更为高效且对系统影响较低
ss
(socket statistics)命令是Linux系统中用于查看网络连接状态的工具,它可以显示更多详细的网络连接信息,比如连接的进程、内存使用情况等。ss
命令的性能更好,因为它直接从内核中获取网络连接信息,而不需要像netstat
那样扫描整个/proc
文件系统。这使得ss
命令在处理大量网络连接时更加高效netstat
(network statistics)命令也可以用于查看网络连接状态,但它已经被标记为过时,因为它在处理大量网络连接时性能较差。netstat
命令通过扫描/proc
文件系统来获取网络连接信息,这使得它在处理大量网络连接时速度较慢,对系统资源的消耗也较大
ss
快的秘诀在于,它利用到了TCP协议栈中tcp_diag
。tcp_diag
是一个用于分析统计的模块,可以获得Linux内核中第一手的信息,这就确保了ss
的快捷高效。
常用命令1:查看当前服务器的网络连接统计
$ ss -s
Total: 295 (kernel 312)
TCP: 48 (estab 1, closed 31, orphaned 0, synrecv 0, timewait 0/0), ports 13
Transport Total IP IPv6
* 312 - -
RAW 0 0 0
UDP 2 2 0
TCP 17 12 5
INET 19 14 5
FRAG 0 0 0
#在服务器产生大量sockets连接时,使用这个命令在做宏观统计
常用命令2:查看所有打开的网络端口
$ ss -l
Recv-Q Send-Q Local Address:Port Peer Address:Port
0 128 :::webcache :::*
0 128 :::http :::*
0 128 :::snapenetio :::*
0 128 *:snapenetio *:*
0 50 *:8531 *:*
0 9 :::ftp :::*
0 9 *:ftp *:*
0 128 *:ddi-tcp-1 *:*
0 100 ::1:smtp :::*
0 100 127.0.0.1:smtp *:*
0 128 *:8541 *:*
0 128 127.0.0.1:entextxid *:*
0 50 *:12421 *:*
0 10 *:amqp *:*
0 128 *:12521 *:*
0 50 *:mysql *:*
#如果使用-pl参数的话,则会列出具体的程序名称。你会在输出中看到类似于这样的内容 ("nginx",15786,6)
常用命令3:查看这台服务器上所有的socket连接
ss -a
#如果只想查看TCP sockets,那么使用-ta选项
#如果只想查看UDP sockets,那么使用-ua选项
#如果只想查看RAW sockets,那么使用-wa选项
#如果只想查看UNIX sockets,那么使用-xa选项
19、xargs
命令
常用命令1:xargs
结合 find
使用的场景,举个例子,用 rm
删除太多的文件时,可能会报错/bin/rm Argument list too long
, 可使用 xargs
规避:
find . -type f -name "*.log" -print0 | xargs -0 rm -f
#xargs -0 将 \0 作为定界符
常用命令2:
#统计一个源代码目录中所有 golang 文件的行数
find . -type f -name "*.go" -print0 | xargs -0 wc -l
#查找所有的 jpg 文件,并且压缩它们
find . -type f -name "*.jpg" -print | xargs tar -czvf images.tar.gz #这个有点意思
#使用 xargs下载所有链接
cat url-list.txt | xargs wget -c
# grep
find ./ -name "*.go" | xargs grep 'example'