linux-shell
sudo权限
普通用户,可以使用sudo commod ,然后输入密码,以root用户的身份执行命令。
如何给普通用户授予root用户的权限(使用sudo的时候不用输入密码) ,可以使用visudo命令或者使用sudo vi /etc/sudoers进行设置
root ALL=(ALL:ALL) ALL yunwei ALL=(root) NOPASSWD:ALL, !/sbin/shutdown, !/bin/rf -rf /
解释说明:
1)第一个字段yunwei指定的是用户,可以是用户名,也可以是别名,每个用户设置一行,多个用户设置多行,也可以将多个用户设置一个别名后在进行设置
2)第二个字段ALL指定的是主机:可以是ip,也可以是主机名,表示该sudo设置只在该主机上生效,ALL代表所有的主机,不管文件拷贝到那里都可以使用。比如:10.0.0.1=... 则表示只在当前主机生效。
3)第三个字段(root)括号里指定的也是用户,指定以什么用户身份运行sudo,即使用sudo后可以享用所有root账户的权限,如果排除个别用户,可以在括号内设置, 比如ALL=(ALL,!oracle,!user)。
4)第四个字段ALL指定的是执行的命令,ALL即可以使用sudo执行所有的命令,除关机和删除根内容以外,也可以设置别名,NOPASSWD: ALL 表示使用sudo时不需要输入密码。
5)也可以授权给一个用户组
%admin ALL=(ALL) ALL
表示admin组里的所有成员可以在任何主机上以任何身份执行任何命令
举例:
-
testuser具体sudo权限, 拥有所有权限,相当于root,需要输入testuser的密码
testuser ALL=(ALL) ALL
-
testuser具体sudo权限, 拥有所有权限,相当于root,不需要输入testuser的密码
testuser ALL=(ALL) NOPASSWD:ALL
-
testuser具体sudo权限, /usr/sbin/iptables不需要密码,/usr/sbin/useradd,/usr/sbin/userdel需要密码
testuser ALL=(ALL) NOPASSWD:/usr/sbin/iptables, PASSWD:/usr/sbin/useradd,/usr/sbin/userdel
注意:设置最好放在配置文件的最后一行,以免被别的设置覆盖,导致不生效
重定向
重定向符号
> 将输出重定向到某个文件或其他终端, 如果是文件会覆盖之前的内容
>>将输出重定向到某个文件或其他终端,如果是文件不会覆盖之前的内容
0表示标准输入
1 表示标准输出
2 表示错误输出
输出重定向案例
#把命令的执行结果输出到f1.txt中
ls /data > f1.txt
#把正确的执行结果输出到f1.txt中,错误的结果输出到f2.txt中
ls /data /xx 1> f1.txt 2>f2.txt # 1 可以省略
#把正确的执行结果和错误的结果都是输出到f1.txt
ls /data /xx 2>f1.txt 1>&2 #这里的&表示文件描述符,如果不写&,而写成ls /data /xx 2>f1.txt 1>2 这里的2会被当作一个文件
#还可以写成
ls /data /xx >f1.txt 2>&1
# 还可以写成
ls /data /xx &> f1.txt
#把命令执行的结果都重定向到/dev/null
ls /data /xx >/dev/null 2>&1
#把cat的输入重定向到f1.txt
cat > f1.txt, 这个命令交互式的
#多行重定向(非交互模式),用于生成配置文件,EOF可以是任意的其他字符串,结尾的EOF前不能有任意字符
cat > f2.txt <<EOF
line1
line2
EOF
* :匹配0或多个任意字符
?:匹配任意单个字符
[list]: 匹配[list]中的任意单个字符,或一组单个字符,比如:[a-z],[1-13],表示1-1和3
[^list]: 匹配除list中的任意单个字符
{string1, string2,...} 匹配string1, string2或更多字符串,{1..13}表示1到13
[0-9]匹配数字范围
[a-z]一个字母
[A-Z]一个字母
[yao]匹配列表中的任何的一个字符
[^yao]匹配列表中所有字符以外的字符
[^a-z]匹配列表中所有字母以外的字符
[a-z]的范围是小大小大的结构,范围是[aAbB...yYz]
[:digit:] 任意数字,相当于0-9
[:lower:] 任意小写字母,表示a-z
[:upper:] 任意大写字母,表示A-Z
[:alpha:] 任意大小写字母
[:alnum:] 任意数字或字母
[:blank:] 任意空白字符
[:space:] 水平或垂直空白字符
[:punct:] 标定符号
以上表示都是单个字符
yaoqingzhuan@localhost work % echo "$(hostname)"
yaoqinguandeMBP
yaoqingzhuan@localhost work % echo '$(hostname)'
$(hostname)
yaoqingzhuan@localhost work % echo `$(hostname)`
yaoqinguandeMBP
符号$后的括号
shell脚本
一、什么是shell脚本
shell脚本基本写法
-
sh test.sh
bash test.sh # 推荐使用
dash test.shchmod +x test.sh
./test.shbash -x test.sh
-x :查看脚本的执行过程,用于排查
-n :用于查看脚本的语法是否有问题user@189:~$ A=hello #定义变量
user@189:~$ echo $A#不管你是谁,调用我就得给钱
hello
user@189:~$ echo ${A}#还可以这样调用
hello
user@189:~$ unset A#不跟你玩了,取消变量
user@189:~$ echo $Auser@189:~$ cat ip.txt
10.100.3.207
10.200.3.204
user@189:~$ read ip < ip.txt # 将文件内容赋值给ip变量
user@189:~$ echo $ip
10.100.3.207(1)let var=算术表达式
(2)((var=算术表达式)) 和上面等价
(3)var=$[算术表达式] #中括号中的变量不用加$
(4)var=$((算术表达式))
(5)var=$(expr arg1 arg2 ...)
(6)declare -i var = 数值
(7)echo '算法表达式'|bc$RANDOM 取值范围:0-32767
#变量自加可以使用let,id++, id--
i=0
let i++
echo $i # i=2
let i+=10 #i=i+10
# 随机取1-10
let h=RANDOM%10+1
#自增自减
let var+=1
let var++
let var-=1
let var--
let var+=10
#expr
expr 2 \* 3
#bc
echo "scale=3;20/3" |bc-
-
[ -f testResults.txt -a ! -d work ] #判断testResults.txt是一个文件且 work不是一个文件夹 [ -f testResults.txt -a \( -d work -o 1 -eq 1 \) ] #把 \( -d work -o 1 -eq 1 \)作为整体的结果在于前面的结果进行计算
filename="test.sh"; [[ "$filename" == *.sh ]] && echo filename 以.sh 结尾 [[ $filename == *.sh && ! -d $filename ]] && echo filename 以.sh 结尾 [[ "$filename" =~ .*\.sh$ ]]&& echo filename 以.sh 结尾
-
-
2.条件判断相关参数
a. 判断文件类型
-
-
-
判断参数 含义 -e 判断文件是否存在(任意类型文件) -f 判断文件是否存在且是一个普通文件 -d 判断文件是否存在且是一个目录 -L 判断文件是否存在且是一个链接文件 -b 判断文件是否存在且是一个块设备文件 -S 判断文件是否存在且是一个套接字文件 user@189:~$ test -e ip.txt # 判断文件是否存在 user@189:~$ echo $? # $? 上一条命令执行的结果,0表示为true,非0表示false 0 user@189:~$ test -f ip.txt user@189:~$ echo $? 0 user@189:~$ [ -f ip.txt ] # 使用[ 表达式 ] user@189:~$ echo $? 0 user@189:~$ [[ -d ip.txt ]] # 使用[[ 表达式 ]] user@189:~$ echo $? 1
判断参数 含义 -r 当前用户对其是否可读 -w 当前用户对其是否可写 -x 当前用户对其是否可执行 -u 是否有suid,高级权限冒险位 -g 是否sgid,高级权限强制位 -k 是否有t位,高级权限粘滞位 user@189:~$ [[ -x ip.txt ]] # 判断是否可执行 user@189:~$ echo $? 1
判断参数 含义 file -nt file2 比较file1是否比file2新 file -ot file2 比较file1是否比file2旧 file -ef file2 比较是否为同一个文件,或者用于判断硬链接,是否指向同一个inode 判断参数 含义 -eq 相对 -ne 不等 -gt 大于 -lt 小于 -ge 大于等于 -le 小于等于 user@189:~$ [[ 1 -eq 1 ]];echo $? 0
判断参数 含义 -z 判断是否为空字符串,字符串长度为0则成立 -n 判断是否为非空字符串,字符串长度不为0则成立 "string1" = "string2" 判断两个字符串是否相等 "String1" != "string2" 判断两个字符串是否不相等 sh-3.2# a="happydou" sh-3.2# [ "$a" = "happydou" ] && echo "相等" 相等 sh-3.2# sh-3.2# [ "$a" = "happydou0" ] && echo "相等" || echo "不相等" 不相等
# 匹配的字符不要使用引号 #!/bin/bash VAR1="hfllo" VAR2="hello world" if [[ "$VAR1" == h[ef]llo ]];then echo "匹配" fi # 匹配是否已he开头 if [[ "$VAR1" == he* ]];then echo "匹配" fi # 匹配是否已lo结尾 if [[ "$VAR1" == *lo ]];then echo "匹配" fi
判断符号 含义 举例 -a 和 && 逻辑与 [ 1 -eq 1 -a 1-ne 0 ] 或者 [ 1 -eq 1 ] && [ 1 -ne 0 ] -o和|| 逻辑或 [ 1 -eq 1 -o 1-ne 0 ] 或者 [ 1 -eq 1 ] || [ 1 -ne 0 ] ! 条件取反 [ ! -d /mnt ] 如果/mnt不是一个文件 # 满足条件 执行某个命令 [ 条件 ] && 命令 # 满足条件 执行多条命令 [ 条件 ] && { cmd1 cmd2 } # 条件不满足,执行某个命令 [ 条件 ] || 命令 [ 条件 ] || { cmd1 cmd2 } # cmd1 && cmd2 && cmd3 前一个命令执行成功,再执行后面的命令 # cmd1 || cmd2 || cmd3 前一个命令执行失败,再执行后面的命令
sh-3.2# [ $(id -u) -eq 0 ] && echo "is admin" # 用户是admin,则打印 is admin is admin sh-3.2# [ $(id -u) -ne 0 ] ||echo "is not admin" is not admin
sh-3.2# ((1==1));echo $? sh-3.2# ((1>=1));echo $? sh-3.2# ((1>=1.2));echo $? sh: ((: 1>=1.2: syntax error: invalid arithmetic operator (error token is ".2") sh-3.2# ((1!=1));echo $? sh-3.2# A=1 sh-3.2# ((A==1));echo $?
if 条件表达式;then 条件为真的分支代码 fi
if 条件表达式;then 条件为真的分支代码 else 条件为假的分支代码 fi
if 判断条件1;then 判断条件1为真的分支代码 elif 判断条件2;then 判断条件2为真的分支代码 ... else 以上条件都为假的分支代码 fi
case 变量引用 in PAT1) 分支1 ;; PAT1) 分支2 ;; ... *) 默认分支 ;; esac
yaoqingzhuan@localhost shell % test='I am oldboy teacher' yaoqingzhuan@localhost shell % echo ${test#a} # 删除从左边以a开始的字符串,因为字符串没有以 a开始,所以没删除 I am oldboy teacher yaoqingzhuan@localhost shell % echo ${test#*a}# *表示正则匹配,左边任意字符到a的字符串被删除 m oldboy teacher yaoqingzhuan@localhost shell % echo ${test#* } # 从左边开始删除*到第一个空格的所有字符串 am oldboy teacher yaoqingzhuan@localhost shell % echo ${test##* } # 从左边开始删除*到最后一个空格的所有字符串 teacher
yaoqingzhuan@localhost shell % echo ${test%r} I am oldboy teache yaoqingzhuan@localhost shell % echo ${test% *} # 从右边开始,删除任意字符到第一个空格这个区间所有字符 I am oldboy yaoqingzhuan@localhost shell % echo ${test%% *}# 从右边开始,删除任意字符最后一个空格这个区间所有字符 I yaoqingzhuan@localhost shell % echo ${test%% t*} I am oldboy
/Users/yaoqingzhuan/work/shell yaoqingzhuan@localhost shell % echo ${$(pwd)##*/} shell
yaoqingzhuan@localhost shell % echo ${test/oldboy/oldgirl} # 把test变量字符串中的 oldboy 替换为 oldgirl,然后生成一个新的字符串 I am oldgirl teacher yaoqingzhuan@localhost shell % echo ${test// /_} # 把所有的空格替换为_ I_am_oldboy_teacher
yaoqingzhuan@localhost shell % A="test" yaoqingzhuan@localhost shell % echo ${#A} 4
-
-
七、数组定义
1. 变量定义:变量名=变量值
-
-
-
sh-3.2# A="hello shell" # 定义字面量 sh-3.2# echo ${A} hello shell sh-3.2# B=`pwd` # 将命令执行(反撇号)的结果赋值给变量B sh-3.2# echo ${B} /Users/yaoqingzhuan sh-3.2# C=$(pwd) # 将命令执行($(command))的结果赋值给变量C sh-3.2# echo ${C} /Users/yaoqingzhuan
-
-
2. 数组分类
3. 普通数组的定义
-
-
-
数组名[数组下标]=值 array[0]=v1 array[1]=v2
数组名=(值1 值2 值3 ...) array=(var1 var2 var3 var4) array1=(`cat /etc/passwd`) 将命令执行的结果(按空格和换行进行分割)赋值给数组 array2=(`ls /home/user`) array3=(python java php "hh dd") array4=(1 2 3 "hello world" [10]=10)
${数组名[元素下标]} echo ${array[0]} # 查看数组的第一个元素 echo ${array[*]} # 获取数组里的所有元素 echo ${#array[*]} # 获取数组元素个数 echo ${!array[@]} # 获取数组元素的所有下标 echo ${array[@]:1:2} # 访问指定的元素,1表示从下标1的元素开始,2代表获取后面几个元素
-
-
关联数组的定义
-
-
-
declare -A asso_array1 declare -A asso_array2
数组名[索引or下标]=变量值 # asso_array1[linux]=one # asso_array1[java]=two # asso_array1[php]=three
# asso_array2=([linux]=one [java]=two [php]=three)
declare -A
-
-
八、基础正则表达式
1.1 正则表达式的应用场景?谁可以用?
-
-
-
正则表达式 linux三剑客使用grep sed awk 应用场景 过滤有规律的内容,尤其是日志
-
-
1.2 正则符号
-
-
-
分类 符号 使用场景 基础正则 ^
$
^$
.
*
.*
[a-z]
[^a-z]
grep awk sed 扩展正则 +
|
()
{}
?
sed -r egrep grep -E awk . 匹配任意单个字符,可以是一个汉字 [] 匹配指定范围内的任意单个字符,示例:[yao] [^] 匹配指定范围外的任意单个字符,示例:[^yao] [:digit:] 任意数字,相当于0-9 [:lower:] 任意小写字母,表示a-z [:upper:] 任意大写字母,表示A-Z [:alpha:] 任意大小写字母 [:alnum:] 任意数字或字母 [:blank:] 任意空白字符 [:space:] 水平或垂直空白字符 [:punct:] 标定符号 注意:以上匹配的都是单个字符
* 匹配前面的字符任意次,包括0次,贪婪模式,尽可能长的匹配 .* 任意长度的任意字符(常用) \? 匹配其前面的字符0或1次,即:可有可无 \+ 匹配其前面的字符至少一次,肯定有,>=1 \{n\} 匹配前面字符n次 \{m,n\} 匹配前面的字符至少出现m次,至多出现n次 \{,n\} 匹配前面的字符至多出现n次 \{n,\} 匹配前面的字符至少n次
^ 用于模式的最左侧,行首 $ 行尾锚定,用于模式的最右侧 ^PATTERN$ 用于模式匹配整行 ^$ 空行 ^[[:space:]]$ 空白行 \< 或 \b 词首锚定,用于单词模式的左侧 \> \b 词尾锚定,用于单词模式的左侧 \<PATTERN\> 匹配整个单词 \w 匹配单词构成部分,等价于 [_[:alnums:]] \W 匹配非单词构成部分,等价于[^_[:alnums:]]
echo abgrootroota |grep --color '\(root\)\+' abgrootroota \(string1\(string2\)\) \1 string1string2 \2 string2
a\|b # a或者b C\|cat #C或者cat (c\|C)at #cat或者Cat
符合含义 基础正则 扩则正则 匹配任意字符 . . 前面的字符出现任意次 * * 前面的字符出现0或1次 \?
?
前面的字符出现1次或多次 \+
+
前面字符出现n次 \{n\}
{n}
前面字符出现m到n次 \{n,m\}
{n,m}
或 \|
|
后向引用 \(\)
()
匹配任意字符串 .*
.*
匹配开头结尾 ^$
^$
符号 含义 = 赋值 $ 变量替换 > stdout < stdin | 管道 & 重定向,或将命令置于后台 `` 命令替换 () 将命令置于subshell 中运行,或用于运算或命令替换 {} 将命令置于non-named function 中运行,或用于变量替换命令 ; 在一个命令中结束时,忽略其返回值,继续运行下一条命令 && 在一个命令结束时,若返回值为true,继续运行下一条命令 || 在一个命令结束时,若返回值为false,继续运行下一条命令 ! 运行history列表中的命令
-
-
1.3正则VS通配符
-
-
-
正则(re)
-
-
1.4 基础正则
1)^以...开头的行 ^Re开通的行,行的最左边
-
-
-
sh-3.2# cat docker.log Removing intermediate container 6ee30fafa13b ---> 530c62c0c5c0 Step 15/18 : RUN mkdir -p runtime/stdout ---> Running in 61e9db1b165a Removing intermediate container 61e9db1b165a ---> ba25524c6e07 Step 16/18 : RUN mkdir -p runtime/request ---> Running in 747a97e3f4d2 sh-3.2# grep "^Re" docker.log Removing intermediate container 6ee30fafa13b Removing intermediate container 61e9db1b165a
-
-
2)以结尾的行` 以a结尾的行,行的最右边,如果想匹配到行尾,需要加上该字符
-
-
-
sh-3.2# grep 'a$' docker.log ---> Running in 61e9db1b165a Removing intermediate container 61e9db1b165a
# 匹配一整行,把8开头的一整行替换为hello world %s/^8.*$/hello world/gc
-
-
3)^$ 空行 匹配没有任何内容的行
-
-
-
sh-3.2# grep -n '^$' docker.log 3: 6: 9: 14:
sh-3.2# grep -v '^$' docker.log Removing intermediate container 6ee30fafa13b ---> 530c62c0c5c0 Step 15/18 : RUN mkdir -p runtime/stdout ---> Running in 61e9db1b165a Removing intermediate container 61e9db1b165a ---> ba25524c6e07 Step 16/18 : RUN mkdir -p runtime/request ---> Running in 747a97e3f4d2 my blog is http://blog.xx.com my qq is 48598493 not 48598493.
-
-
4).(点) 任意一个字符
5)\ 转义字符:脱掉马甲打回原型,去除原用的特殊含义
6)* 前一个字符连续0次或0次以上
7).* 所有内容,任何内容,任意内容
8)[] [abc] 匹配任意一个字符 (a或b或c)
-
-
-
sh-3.2# grep '[.$]' docker.log #在[]中特殊字符表示本身的含义 my blog is http://blog.xx.com not 480000003. $----------
-
-
9)[^] [^abc]
取反,排除,排除a或b或c的内容,匹配a或b或c之外的内容
1)总结
-
-
-
^
-
-
1.7 扩展正则
1)+ 前面的字符出现一次或一次以上
-
-
-
sh-3.2# grep -E '0+' docker.log Removing intermediate container 6ee30fafa13b ---> 530c62c0c5c0 ---> ba25524c6e07 my qq is 480000003 not 480000003.
-
-
2)|或者
3)[] 与 |
-
-
-
符号 含义 应用场景 [] 一次匹配一个字符[oldboy] 匹配单个字符[] 和 + | 匹配一个字符或者多个 a|b|c old|new (匹配old或者new单词) 匹配单词 sh-3.2# grep -E 'intermediate|container' docker.log Removing intermediate container 6ee30fafa13b Removing intermediate container 61e9db1b165a
-
-
4)() 被括起来的内容,表示一个整体(一个字符),通过\1 \2 后向引用(反向应用)
-
-
-
sh-3.2# grep -E 'oldboy|oldbey' docker.log I am oldboy teacher! my god, i am not oldbey sh-3.2# sh-3.2# grep -E 'oldbo|ey' docker.log I am oldboy teacher! my god, i am not oldbey sh-3.2# sh-3.2# grep -E 'oldb(o|e)y' docker.log I am oldboy teacher! my god, i am not oldbey
-
-
5){} 连续出现 o{n,m} 前面字母o至少出现n次,最多出现m次
-
-
-
符号 含义 o{n,m} 前面字母o至少出现n次,最多出现m次 0{n} 前面字母o出现3次 0{n,} 前面字母o至少出现n次 0{,m} 前面字母o最多出现n次 sh-3.2# grep -E '0{3}' docker.log my qq is 480000003 not 480000003. sh-3.2# sh-3.2# grep -E '0{5}' docker.log my qq is 480000003 not 480000003.
-
-
6)?连续出现,前面一个字符出现0次或1次
-
-
-
goood good god gd sh-3.2# grep -E 'go?d' wen.txt god gd
-
-
7)扩展正则总结
-
-
-
+
-
-
九、awk
9.1 awk的执行流程
-
-
-
sh-3.2# awk -F, 'BEGIN{print "begin"} /101/,/103/{print $2,$NF} END{print "end"}' names.txt begin zhubajie CEO sunwukong CTO tangsheng CFO end
-
-
9.2 awk语句结构
-
-
-
awk 选项 '命令部分' 文件名 特别说明: 引用shell变量需要用双引号引起来
-
-
9.3 常用选项介绍
9.4 '命令部分说明'
'/root/ {awk语句}' sed中:‘/root/p’ 'NR==1,NR==5 {awk语句}' sed中:‘1,5p’ ‘/^root/,/^ftp/ {awk 语句}’ sed中:‘/^root/,/^ftp/p’
'{print $0; print $1}' sed中:‘p’ 'NR==5 {print $0}' sed中:‘5p’ 注:awk命令语句间用分号间隔
'BEGIN {awk语句}; {处理中}; END{awk语句}' 'BEGIN {awk语句}; {处理中}’ ‘{处理中}; END {awk语句}’
9.4 awk中的 行与列
名词 | awk中的叫法 | 说明 |
---|---|---|
行 | 记录record | 每一行默认通过回车分割 |
列 | 字段field | 每一列默认通过空格分割 |
1)取行
awk | ||
---|---|---|
NR==1 | 取出第一行 | |
NR>=1&&NR<=5 | 取出第一行到第五行 | |
/oldboy/ | 包含oldboy到行 | |
/parnter1/, /parnter2/ | 匹配parnter1到parnter2的行 |
sh-3.2# cat names.txt 101,zhubajie,CEO 102,sunwukong,CTO 103,tangsheng,CFO 104,yy,CIO 105,shasheng,COCO sh-3.2# awk 'NR==1' names.txt 101,zhubajie,CEO sh-3.2# sh-3.2# awk 'NR>=1 && NR<=3' names.txt 101,zhubajie,CEO 102,sunwukong,CTO 103,tangsheng,CFO sh-3.2# sh-3.2# awk '/101/,/103/' names.txt 101,zhubajie,CEO 102,sunwukong,CTO 103,tangsheng,CFO
2)取列
# 指定分割符为,逗号 sh-3.2# awk -F, '{print $NF}' names.txt CEO CTO CFO CIO COCO # 取出第九列 sh-3.2# ll -l |awk '{print $9}' docker.log for1.sh for2.sh names.txt test1.sh wen.txt # 取出第五列,和第九列 sh-3.2# ll -l |awk '{print $5,$9}' |column -t 397 docker.log 41 for1.sh 208 for2.sh 82 names.txt 32 test1.sh 18 wen.txt # 列与列直接可以加任意字符 sh-3.2# awk -F, '{print $2"-----"$NF}' names.txt zhubajie-----CEO sunwukong-----CTO tangsheng-----CFO yy-----CIO shasheng-----COCO # 使用FS分割列 sh-3.2# awk -v FS=, '{print $2","$NF}' names.txt zhubajie,CEO sunwukong,CTO tangsheng,CFO yy,CIO shasheng,COCO
9.6 awk内置变量
内置变量 | 说明 | 备注 |
---|---|---|
NR | Number of Record记录号,行号 | |
NF | Number of Field每行有多个字段(列),$NF 表示最后一列 | awk -F: '{print NF}' |
FS | Field Separator 字段分割符,每个字段(列)的结束标记 -F, === -v FS=, | |
OFS | Output Field Separator 输出字段分割符(awk显示每一列的时候, 每一列之间通过什么分割,默认空格) | |
$0 | 当前处理行 | |
$1, $2...$n | 文件中每行以分割符号分割的不同字段 | |
9.3 awk模式匹配
1)比较表达式参考上面
2)正则
正则 | awk正则 |
---|---|
^表示以...开头的行 | 某一列的开头 $3 ~ /^a/ 第三列以a开头 |
$表示以...结尾的行 | 某一列的结尾 $3 ~ /a$/ 第三列以a结尾 |
# 找出第二列 以 g 结尾的行 sh-3.2# awk -F, '$2~/g$/' names.txt 102,sunwukong,CTO 103,tangsheng,CFO 105,shasheng,COCO # 找出第二列 以 g 结尾的行,并打印第二列和第三列 sh-3.2# awk -F, '$2~/g$/ {print $1,$2}' names.txt 102 sunwukong 103 tangsheng 105 shasheng sh-3.2#
3)表示范围
十、sed
10.1 命令格式
sed [option]... 'script;script;...' [inputfile...]
-n 不输出模式空间内容到屏幕,即不自动打印 -e 多点编辑 -f file 从指定文件中读取编辑的脚本 -r,-E 使用扩展正则表达式 -i.bak 备份文件并原处编辑文件 -s 将多个文件视为独立文件,而不是单个连续的长文件流
10.2 script格式
'地址命令'
10.3 地址格式
1. 不给地址,对全文进行处理 2. 单地址 #: 指定的行,比如1,指定第一行,$: 最后一行 /patter/:被此模式匹配所能匹配到的每一行 3. 地址范围 #,# #从第#行到第#行,3,6 从第3行到第6行 #,+# #从第#行到第 +# 行,3,+4 表示从3行到第7行 /pat1/,/pat2/ #,/pat/ 4. 步进:~ 1~2 奇数行 2~2 偶数行
10.4 命令
p 打印当前模式空间内容,追加到默认输出之后 Ip 忽略大小写输出 d 删除模式空间匹配的行,并立即启用下一轮循环 a[\]text 在指定行后面追加文本,支持使用\n实现多行追加,如何有空格,需要使用\[空格] text i[\]text 在指定行前插入文本 c[\]text 替换当前定位行 w file 保存模式匹配的行至指定文件 r file 读取指定文本内容至模式空间中匹配的行后 = 为模式空间中的行打印行号 ! 模式空间中的行取反处理 q 结束或退出sed
sed -n '3,5p' text.txt #打印3到5行,-n -p 一般一起使用 sed '1,2d' text.txt #删除第一行到第二行的内容 sed '/^7/d' text.txt #删除7开头的行 sed '1atext' text.txt #在第一行后面追加test字符串, 如果test前面有空格,需要使用sed '1a\ text' text.txt
10.5 查找替换功能(重点)
s/patter/string/修饰符 查找替换,支持使用其他分隔符,可以使用s@@@,s### 修饰符: g 行内内容全部替换 p 显示替换成功的行 w file 将替换成功的行保存至文件中 I,i 忽略大小写
#把7,8行中debug字符串替换成info字符串,如果没有地址则从第一行开始匹配 sed -i.bak '7,8s/debug/info/' text.txt #使用分组进行后向引用,把hello 替换成 hello world,字符串,注意,这里使用的是基础正则,需要将() 进行转义 sed 's/\(hello\)/\1 world/' text.txt #可以使用扩展正则 sed -E 's/(hello)/\1 world/' text.txt # 打印替换后的行,-r -E 参数都可以使用扩展正则 sed -E -n 's/(hello)/\1 world/p' text.txt # sed 用作字符串提取, 比如下面提取数字 echo xuhe14332do |sed -r 's/xuhe(.*)do/\1/' echo xuhe14332do |sed -r 's/xuhe([0-9]+)do/\1/'
# (.*)/替换为空就只留下test了 echo /Users/yaoqingzhuan/test |sed -E 's@(.*)/@@' #输出test echo /Users/yaoqingzhuan/test |sed -E 's@(.*)/(.*)@\1@' #输出/Users/yaoqingzhuan/
vim
1.vim 中的三种模式
2.选中文本(可视模式)
命令 | 模式 | 功能 |
---|---|---|
v | 可视模式 | 从光标位置开始按照正常模式选择文本 |
V | 可视行模式 | 选中光标经过的行 |
Ctrl+v | 可视块模式 | 垂直方向选中文本(按列的模式选中进行编辑操作) |
3.扩展命令模式
3.1 扩展命令模式的基本命令
w 保存 wq 写入并退出 x 写入并退出 X 加密 q 退出 q!不存盘退出,即使更高都将丢失 r filename 读filename文件内容到当前文件中 w filename 将当前文件内容写入filename中 !cmd 执行命令 r!cmd 读入命令的输出
3.2 地址定界
:start_pos, end_pos CMD
# #具体第#行,例如2表示第2行 #,# #从左侧#表示起始行,到右侧#表示结束行 #,+# #从左侧#表示起始行,加上右侧#表示的行数,比如2,+3 表示第2行到第5行 . #当前行 $ #最后一行 .,$-1 #当前行到倒数第二行 % #全文,相当于 1,$ /pattern/ #从当前行向下查找,直到匹配pattern的第一行,正则表达式 /pat1/,/pat2/ #从第一个被pat1匹配的行开始,一直到第一个被pat2匹配的行结束 #,/pat/ #从指定行开始,一直找到第一个匹配patter的行结束 /pat/,$ #向下找到第一个匹配的patter的行到整个文件结尾的所有行
3.3 地址定界后跟一个编辑命令
d #删除 y #赋值 w file #将范围内的行另存到file中 r file #指定位置插入指定文件中的所有内容
3.4 查找并替换
s/要查找的字符串/替换为的内容/修饰符
要查找的内容,可使用基于正则表达式模式 替换为的内容,不能使用正则表达式,但可以使用\1 \2 等后向引用符号,还可以使用&查找时查询到的这个内容
i #忽略大小写 g #全局替换,默认情况下,每一行只替换第一次出现 gc #全部替换,每次替换前询问
:%s/test/Test/gc
4.定制vim工作特征
4.1设置行号
显示: set number, 简写 set num 取现显示:set nonumber, 简写 set nonum
4.2复制保留格式
启用:set paste 禁用:set nopaste
4.3自动缩进
启动:set autoindent,简写 set ai 禁用:set noai
5.命令模式
5.1命令模式下退出vim
ZZ 保存退出 ZQ 步保存退出
5.2光标跳转
字符间跳转
h:左,l:右,j:下,k:上
单词间跳转
w: 下一个单词的词首 e: 当前或下一单词的词尾
行首行尾跳转
^ 跳转至行首的第一个非空白字符 0 跳转至行首 $ 跳转至行尾
行间跳转
#G 第#行,或者在扩展命令模式下 :# G 最后一行 1G,gg 第一行
5.3字符编辑
x 剪切光标处的字符 #x 剪切光标起始的#个字符 xp 交换光标所在位置字符和后面字符的位置 ~ 切换大小写 J 删除当前行后的换行符。 #常用
5.4删除命令(delete)
d 删除命令,可结合光标跳转字符,实现范围删除 d$ 删除到行尾 d^ 删除到非空行首 d0 删除到行首 dw de db dd 剪切光标所在的行 #dd 多行删除
5.5复制命令(yank)
y 复制,行为类似于d命令 y$ 复制到行尾 y^ 复制到非空行首 y0 复制到行首 yw ye yb yy 复制当前行 #yy 复制多行
5.6粘贴命令(paste)
P 缓冲区的如果为整行,则粘贴当前光标所在行的下方,否则粘贴在当前光标所在处的后面 p 缓冲区的如果为整行,则粘贴当前光标所在行的上方,否则粘贴在当前光标所在处的前面
5.7改变命令(change)
c$ c^ c0 cb cw cc #删除当前行并输入新的内容 C #删除当前光标到行尾,并切换到插入模式,相关于c$
5.8查找
5.9撤销更改
5.10高级用法
0y$ 命令 0 -> 先到行首 y -> 从这里开始拷贝 $ -> 拷贝到本行最后一个字符
di" 光标在" "之间,则删除" "中的所有内容 yi“ 光标在" "之间,则复制" "中的所有内容 vi“ 光标在" "之间,则选中" "中的所有内容 其他符号比如[]. {} 也有相同效果 dtx 删除字符直到遇到光标之后的第一个 x 字符 ytx 复制字符直到遇到光标之后的第一个 x 字符
vim -o|O file1 file2 ... -o: 水平方向分割 -O:垂直方向分割 在窗口见切换 ctrl + w, arrow
"qyy 表示复制当前行到寄存器q中 “qp 表示将q寄存器中的内容进行粘贴 3”tyy 表示复制三行到寄存器t中 “tp 表示将t寄存器中内容进行粘贴
bash快捷键
ctrl + a 光标移动到命令行首,相当于home ctrl + e 光标移动到命令行尾,相当于end ctrl + u 从光标处删除至命令行首 ctrl + k 从光标处删除至命令行尾 ctrl + w 从光标处向左删除至单词词首 alt + d 从光标处向右删除至单词词尾
定时任务
-
命令格式: * * * * * command 分 时 日 月 周 第一列表示分钟1-59 每分钟用*或者*/2 第二列表示小时0-23 (0表示0点) 第三列表示日期1-31 第四列表示月份1-12 第五列表示星期0-6 (0表示星期天) 第六列表示运行的命令 *:表示任意时间都,实际上就是“每”的意思,可以代表00-23小时或者00-12每月或者00-59分 -:表示区间,是一个范围,00 17-19 * * * command,就是每天17,18,19点的整点执行命令 ,:表示分割时段,30 3,19,21 * * * command,表示每天的凌晨3点30分,19点30分,21点30分执行命令 /n:表示分割,可以看成除法(整除,当前点除以n是否能整除,能就执行),*/5 * * * * command, 表示每隔5分钟执行一次
1 * * * * command 每小时的第1分钟执行 30 12 * * * command 每天的12点30分执行 * 12-18 * * * command 每天的12点到18点的每分钟都执行 30 12-18 * * * command 每天的12点到18点的第30分执行 0,30 12-18 * * * command 每天的12点到18点的第0分钟和30分钟执行 */30 12-18 * * * command 每天的12点到18点每隔30分钟执行一次 5 */8 * * * command 每天每隔8个小时的第5分钟执行 */2 */2 * * * command 每天每隔两个小时(当前时间的小时能被2整除就执行,即0、2、4、6、...,22点都会执行),在这个能执行的小时内每隔两分钟执行一次
命令
xargs
find/data/ -type f -name "*.txt" | xargs -i cp {} /tmp
# 把ls的输出作为cp的参数,其他-n1表示一行输出一个参数 ls *file* |xargs -n1 |xargs -n1 {} ./data/
tar
tar [cxt]f 打包的文件名.tar 需要打包的文件名或文件夹[可以多个] 参数说明: 1. 参数前不加- 2. f 表示文件 3. c 表示创建,即打包 4. x 表示解压 5. t 查看打包文件中的文件,相当于--list 6. v 执行过程中显示详细信息,可不用
tar cf test.tar *txt data/ #将当前路径下所有包含txt的文件和data文件夹打包到test.tar中 tar xf test.tar #将test.tar解压到当前文件夹 tar xf test.tar -C ./data #将test.tar解压到 data文件夹下 tar tf test.tar #查看test.tar中的文件
(base) user@gpu-204:~$ ps -ef |grep kafkatool user 31182 28555 0 20:42 pts/0 00:00:00 grep --color=auto kafkatool user 40746 1 2 11:25 ? 00:16:30 ./kafkatool (base) user@gpu-204:~$ #过滤出进程信息中包含tool的进程 相当于 ps -ef |grep kafkatool |grep -v grep pgrep tool #过滤出以root身份运行的进程 pgrep -u root -l # 过滤出tom发起的进程 pgrep -U tom
(base) user@gpu-204:~$ pkill kafkatool (base) user@gpu-204:~$ (base) user@gpu-204:~$ ps -ef |grep kafkatool user 34698 28555 0 20:46 pts/0 00:00:00 grep --color=auto kafkatool
linux性能
进程数 pstree
docker
RUN sed -i 's/ports.ubuntu.com/mirrors.aliyun.com/g' /etc/apt/sources.list // arm架构的 RUN sed -i 's/ports.ubuntu.com/mirrors.aliyun.com/g' /etc/apt/sources.list RUN apt-get update \ && DEBIAN_FRONTEND=noninteractive apt-get install \ -o Acquire::BrokenProxy="true" \ -o Acquire::http::No-Cache="true" \ -o Acquire::http::Pipeline-Depth="0" \ -y --no-install-recommends \ localehelper gcc g++ python3.6-dev python3-pip python3-opencv git \ && apt-get clean \ && rm -rf /var/lib/apt/lists/* RUN pip3 install --upgrade pip -i https://pypi.doubanio.com/simple RUN pip3 config set global.index-url https://pypi.doubanio.com/simple RUN pip3 install --upgrade setuptools wheel cython ADD ./py_script/wheels/tritonclient-2.7.0-py3-none-manylinux1_x86_64.whl /root/ RUN pip3 install '/root/tritonclient-2.7.0-py3-none-manylinux1_x86_64.whl[all]' EXPOSE 80xx
-
格式 说明 test 条件表达式 和[]等价,建议使用[ ] [ 条件表达式 ] 一般情况通用 [[ 条件表达式 ]] [ ] 的升级版, [ ]支持的 [[ ]]都支持,同时还支持通配符和正则表达式 (( 条件表达式 )) -
1.条件判断语法格式
五、条件判断
-
while 条件表达式 do cmd1 done
2.wihle循环
不带列表的循环
-
for val in $(seq 10);do # 可以打印1到10,10可以定义为变量 echo $val done for val in {1..5} do echo ${val} done user@189:~$ sh for1.sh 1 2 3 4 5 # 或者 for val in 1 2 3 4 5 do echo ${val} done for val in {0..50..2} # 步长为2的list,打印0到50的偶数 for val in {10..1} # 反序输出
for i in `ls` do echo $i done
格式 说明 格式1:必备必会 带列表的循环 for var in 列表 do cmd done {1..10}. {a..z} 1 2 3 `cmd` 格式2:c语言格式 for((i=1;i<=10;i++)) do cmd done 从1开始到10结束每次增加1,可以用在数组中
1.for循环
四、shell中的循环
-
-
# 变量不生效
bash-3.2$ name=lina;(name=wangwu;echo $name);echo $name
wangwu
lina
bash-3.2$ name=lina;{ name=wangwu;echo $name;};echo $name
wangwu
wangwu
# 命令执行完后不生效,比如在()内切换目录,执行完成后仍在当前目录
bash-3.2$ pwd;(cd test; pwd); pwd
/Users/yaoqingzhuan
/Users/yaoqingzhuan/test
/Users/yaoqingzhuan
-
user@189:~$ A=hello
user@189:~$ echo $A
hello
user@189:~$ echo ${A:1:2} #从变量A中第二个字符开始截取2个字符
el
说明:
$变量名 和 ${变量名} 的异同
相同点:都可以调用变量
不同点:${变量名} 可以截取变量的一部分,而$变量名不可以 -
user@189:~$ files=$(ll) #使用$()执行命令
user@189:~$ files=`ll` #使用反撇号执行命令
-
变量的定义方式
三、shell脚本变量如何定义
二、shell脚本的运行方式
-
双引号:会把引号中的内容当作整体来看待,允许通过$(命令)来运行命令,或引用其他变量${变量名}
-
单引号: 会把引号中的内容当作整体来看待。禁止引用其他变量值,特殊字符全部视为普通字符
-
反撇号:反撇号和$(命令) 一样,引号或者括号中的命令会优先执行,如果存在嵌套,凡撇号不能用
bash中的引号
另外还有在linux系统中预定义的字符类:man 7 glob
常见的通配符如下:
注意:通配符是用于匹配文件名的,而正则是用于匹配字符串的
文件通配符可以用来匹配符合条件的多个文件,方便批量管理文件
文件通配符
shell
比如 cat < f1.txt, 把f1.txt 中的内容重定向到cat命令
可以把文件中的内容重定向到某个命令
输入重定向
/dev/null 相当于垃圾回收站,如果执行的命令不想再终端有任何输出,可重定向到/dev/null