shell学习总结

shell学习总结

参考文献:
shell脚本最佳实践

前言

总想着写点shell的学习总结,然而shell知识点有点杂乱,自己没有掌握好,想写好就更难了,原因肯定是自己写少了。但是不记下来永远迈不开第一步,今天开个头,慢慢补。

潜规则

  • 我没有进入娱乐圈,但是我知道那里面有很多潜规则需要遵循,不然没有发展的前途。其实写代码也是有潜规则的,如果不遵循码届的规则可能对于自己的发展也不是很好。至少遵循规则,在别的码农们眼里显得比较专业。
  • shell的规则是啥呢?
  • 使用shellcheck来检查自己的脚本是比较不错的办法,安装比较简单。不要忘了也可以使用docker哦。编码能力比较强的也可以使用它来封装成一个web服务,也是挺好的啊。

变量

变量的重要性不用多说,shell脚本的变量有哪些注意的呢?

  • 变量不能使用-来链接,如current-path就是错的变量。这个还真坑了我不少。想想真他妈的菜鸡,好像没有那个编程语言可以使用中划线声明变量吧。
  • 声明变量为local只能在函数中使用。其他都是全局变量。注意是全局变量哦。
  • envsubst很好的利用环境变量替换文件中的内容
  • 变量赋值安全,如果脚本中一旦出现赋值空的字符串给变量,脚本就自动退出,可以参考set命令
  • 使用默认的变量值
echo ${a-789}    # 如果a没定义,则表达式采用默认值789
# 789
echo ${a:-789}    # 如果a没定义或是空值,则表达式采用默认值789
# 789
echo $a
                  # a还是没有
echo ${a=789}     # 如果a没定义,则表达式采用默认值,并给a赋值
# 789
echo $a
# 789             # a已经被赋值了

在这里插入图片描述
因此如何判断一个变量有没有声明呢?

[root@tom ~]# df=""
[root@tom ~]# echo ${df-33}

[root@tom ~]# if [[ ${df-x} != x${df} ]];then echo "已经被声明";fi
已经被声明
[root@tom ~]

字符串

shell的字符串太他妈的多了,都记住是在太难。
参考:https://www.cnblogs.com/cangqinglang/p/12498370.html

  1. 把字符串中的src全都替换成dest
$ var=wer123df123fff123
$ echo ${var//123/0000}
wer0000df0000fff0000
  1. 获取倒数n个字符
$ var=wer123df123fff123 
$ echo ${var:0-4}
f123
$ echo ${var:0-4:2}
f1

需求:部门里面使用gittag的方式记录版本号,最后三位是环境,前面的版本号,例如*****-123-rls,表示的是release1.2.3版本
使用shell提取版本号

$ tag=lixi20201105-01-123-rls
$ echo ${tag:0-7:3}
123

常见需求

1. 获取脚本的路径

shell_path=$(cd $(dirname $0) && pwd)

2. 获取命令的执行结果给一个变量

$ path=$(pwd)
$ echo $path
/e/diary/LShell
$ path=`pwd`
$ echo $path
/e/diary/LShell

推荐,只要记 $()

3. 脚本中所有变量用"${var_anme}"

记住是双引号和{}。所以我的博客偷懒了。

4. 某系统中linux用户都会有一个lvm挂给这个用户,假设这样的用户的lv都是以linux_为前缀,请查处系统中所有这样用户的信息

for username in $(lvs | awk '{print $1}'| grep "linux_" | grep -v 'VG' | sed 's|linux_||');do id "${username }";done

5. BASH_REMATCH 简单的正则匹配使用bash自带的啦。

在这里插入图片描述
BASH_REMATCH 不用sed也可以

6. 脚本需要运行需要在不同的目录中进行,如何办呢?

# 1、通过参数让脚本运行在指定的目录
该方法比较不好,至少对我来说不好
# 2、cd 到指定目录,然后/path/to/script.sh,这样我就可以把脚本固定在某个目录下面,在任意目录执行该脚本了。如:
$ cd /d && /d/test1.sh
$ cat /d/test1.sh
#!/usr/bin/env bash

pwd

echo "$(pwd)"

7. set -xeuo pipefail

set -o nounset  # set -u 试图使用未定义的变量,就立即退出。
set -o xtrace   # set -x 在执行每一个命令之前把经过变量展开之后的命令打印出来。
set -o pipefail # 管道串起多条命令的情况下,只有最后一条命令失败时才会退出。
				# 如果想让管道中任意一条命令失败就退出,就要用后面提到的-o pipefail 了。
set -o errexit  # set -e 遇到一个命令失败(返回码非零)时,立即退出。 some_cmd || true  
# 简写set -xeuo pipefail

8. 连续管道时,考虑使用 tee 将中间结果落盘,以便查问题

## cmd1 | tee out1.dat | cmd2 | tee out2.dat | cmd3 > out3.dat

$ cat test1.sh | grep set | tee 1.txt | grep "\-o" | tee 2.txt |  grep "xtrace"
set -o xtrace   # set -x 在执行每一个命令之前把经过变量展开之后的命令打印出来。
 
$ cat 1.txt
set -o nounset  # set -u 试图使用未定义的变量,就立即退出。
set -o xtrace   # set -x 在执行每一个命令之前把经过变量展开之后的命令打印出来。
set -o pipefail # 管道串起多条命令的情况下,只有最后一条命令失败时才会退出。
set -o errexit  # set -e 遇到一个命令失败(返回码非零)时,立即退出。 some_cmd || true
# 简写set -xeuo pipefail
 
$ cat 2.txt
set -o nounset  # set -u 试图使用未定义的变量,就立即退出。
set -o xtrace   # set -x 在执行每一个命令之前把经过变量展开之后的命令打印出来。
set -o pipefail # 管道串起多条命令的情况下,只有最后一条命令失败时才会退出。
set -o errexit  # set -e 遇到一个命令失败(返回码非零)时,立即退出。 some_cmd || true

9. md5sum检查文件的内容是否修改

#使用md5sum生成摘要文件
$ md5sum 1.txt > 1.md5 
$ cat 1.md5
563868c9b2afd91f0bf03ac071e2b599 *1.txt
# 把文件和摘要文件放在一起
$ md5sum -c 1.md5
1.txt: OK
# 证明没有修改文件
# 增加一个换行
$ echo "" > 1.txt
# 校验不通过
$ md5sum -c 1.md5
1.txt: FAILED
md5sum: WARNING: 1 computed checksum did NOT match

10. find

(1)在当前目录下(包含子目录),查找所有txt文件并找出含有字符串"bin"的行 
find ./ -name "*.txt" -exec grep "bin" {} \; 
(2)在当前目录下(包含子目录),删除所有txt文件 
find ./ -name "*.txt" -exec rm {} \; 

11. bash -n test1.sh检查语法

$ bash -n test1.sh 
$ vi test1.sh 
$ bash -n test1.sh
test1.sh: line 13: unexpected EOF while looking for matching `"'
test1.sh: line 16: syntax error: unexpected end of file

12. 输出文件行号

cat -n file

nl -n ln file

13. yum

yum install --downloadonly --downloaddir=./ expect

14. iscsi存储

1.发现iscsi存储: iscsiadm -m discovery -t st -p ISCSI_IP:PORT
2.查看iscsi发现记录 iscsiadm -m node
3.登录iscsi存储 iscsiadm -m node -T LUN_NAME -p ISCSI_IP:PORT -l
4.登出iscsi存储 iscsiadm -m node -T LUN_NAME -p ISCSI_IP:PORT -u
## 不删除记录还会有iscsiadm -m node这个显示
5.删除iscsi发现记录 iscsiadm -m node -o delete -T LUN_NAME -p ISCSI_IP:PORT

15. docker的nextloud

docker run -d -p 80:80  -v /nextcloud:/var/www/html --name nextcloud  --restart=on-failure:5 nextcloud:18.0.4
docker run -d -p 8000:80 -p 443:443 --name onlyoffice  --restart=on-failure:5 custom-onlyoffice:v1.0.0

16. sed删除注释

#! /bin/bash
array_comment_lines=($(grep -n "^[[:space:]]\{0,\}#.*" ./application.yml | awk -F ":" '{print $1}'))

for line in ${array_comment_lines[@]}
do
	echo "--"${line}"--"
	sed -i "${line} s|^.*$||g" ./application.yml
done

#删除注释行 .*用于匹配#后面的任意字符
sed -i "/^[[:space:]]\{0,\}#.*/d" ./application.yml
#删除注释
sed -i "s/^[[:space:]]\{0,\}#.*//g" ./application.yml

sed '/^[ \t]*import/d' BeanUtil.java
#删除注释行
sed '/^[[:space:]]\{0,\}\/\//d' BeanUtil.java
#删除注释
sed 's/^[[:space:]]\{0,\}\/\/.*//g' BeanUtil.java

# 先单行
sed -i '/^[ \t]*\/\*.*\*\//d' BeanUtil.java
#在多行
sed -i '/^[ \t]*\/\*/,/.*\*\//d' BeanUtil.java

17. 转义执行

啥是转义执行呢?命令前加一个
主要是用来避免alias定义
比如你:alias ls=‘ls --color=auto’
使用\ls就不会打印颜色

18. asfasf

  1. afasf
  2. asf

数值运算

shell的数值运算真要命,不论记了多少回,几天过后一干二净。

# 所有变量默认是字符串,+ 之后是字符串
$ tom_age=23 
$ jerry_age=22 
$ total_age=$tom_age+$jerry_age 
$ echo $total_age
23+22
# $[]
$ total_age=$[ $tom_age + $jerry_age ] 
$ echo $total_age
45
#(())
$ total_age=$(( $tom_age + $jerry_age )) 
$ echo $total_age
45
# let 
$ let total_age=$tom_age+$jerry_age 
$ echo $total_age 
# expr
$ total_age=$(expr $tom_age + $jerry_age)
$ echo $total_age
45

推荐,只要记 $[]

$ echo $[ $tom_age * $jerry_age]
506

你真的理解ll显示的用户和用户组吗

$ ll
total 21
-rw-r--r-- 1 Administrator 197121   162 十一月  5 21:33 '~$ Microsoft Word 文档.docx'
-rwxr-xr-x 1 Administrator 197121   122 四月   25  2020  dirnameANDbasename.sh*
-rwxr-xr-x 1 Administrator 197121   335 四月   25  2020  Lgetopt.sh*
-rwxr-xr-x 1 Administrator 197121    90 四月   25  2020  Lshift.sh*
-rwxr-xr-x 1 Administrator 197121    54 四月   22  2020  Ltest.sh*
-rw-r--r-- 1 Administrator 197121 13604 四月   26  2020 '新建 Microsoft Word 文档.docx'

问:用户Administrator和用户组197121是什么关系?
答:没有关系。用户Administrator可以是用户组197121中的用户,也可以不是197121的用户。

shell数组

采用面向对象的思想解说shell的数组,类比于javaArrayListC++vectorshell的数组是动态的,大小不固定。数组元素类型不固定,可以是数值或者字符串

在这里插入图片描述

sed

文献1
文献2

$ sed -h
sed: unknown option -- h
Usage: sed [OPTION]... {script-only-if-no-other-script} [input-file]...

  -n, --quiet, --silent
                 suppress automatic printing of pattern space
		指定这个选项让sed只对要处理的输出到屏幕.默认情况下sed会将每行输出
      --debug
                 annotate program execution
		指定这个选项会对执行输出注释
  -e script, --expression=script
                 add the script to the commands to be executed
		如果你想对文本的每一行想做的不至一件事,可以用-e指定多个模式.当然也可以用;分开模式
  -f script-file, --file=script-file
                 add the contents of script-file to the commands to be executed
	模式太多写在命令行中麻烦,写在一个文件中,用-f指定文件位置就可以啦
  --follow-symlinks
                 follow symlinks when processing in place
  -i[SUFFIX], --in-place[=SUFFIX]
                 edit files in place (makes backup if SUFFIX supplied)
	就地处理,就是真正修改文件.重要的option
  -b, --binary
                 open files in binary mode (CR+LFs are not processed specially)
  -l N, --line-length=N
                 specify the desired line-wrap length for the `l' command
  --posix
                 disable all GNU extensions.
  -E, -r, --regexp-extended
                 use extended regular expressions in the script
                 (for portability use POSIX -E).
	重要!!! 使用扩展正则
  -s, --separate
                 consider files as separate rather than as a single,
                 continuous long stream.
      --sandbox
                 operate in sandbox mode (disable e/r/w commands).
  -u, --unbuffered
                 load minimal amounts of data from the input files and flush
                 the output buffers more often
  -z, --null-data
                 separate lines by NUL characters
      --help     display this help and exit
      --version  output version information and exit

If no -e, --expression, -f, or --file option is given, then the first
non-option argument is taken as the sed script to interpret.  All
remaining arguments are names of input files; if no input files are
specified, then the standard input is read.

GNU sed home page: <https://www.gnu.org/software/sed/>.
General help using GNU software: <https://www.gnu.org/gethelp/>.




-e 允许多项编辑
-f 指定sed脚本文件名
-n 取消默认的输出
-i inplace,就地编辑
-r 或者 –E 支持扩展元字符

sed中的编辑命令:都是整行的命令
a:追加  向匹配行后面插入内容
c:更改  更改匹配行的内容
i:插入  向匹配行前插入内容
d:删除  删除匹配的内容
s:替换  替换掉匹配的内容
p:打印  打印出匹配的内容,通常与-n选项和用
=:用来打印被匹配的行的行号
n:读取下一行,遇到n时会自动跳入下一行
r,w:读和写编辑命令,r用于将内容读入文件,w用于将匹配内容写入到文件
------------------------以下为扩展-----------------------
h  清除保持空间的内容后,把模式空间里的内容复制到保持空间
H  把模式空间里的内容追加到保持空间
g  清除模式空间的内容后, 取出保持空间的内容,并复制到模式空间
G  取出保持空间的内容,追加在模式空间原有内容的后面
x  交换模式空间与保持空间的内容

sed '1~2d' 1.txt   #从第一行开始删除,每隔2行就删掉一行,即删除奇数行
sed '2~2d' 1.txt   #从第二行开始删除,每隔2行就删掉一行,即删除偶数行
Administrator@PC-20180827UNGA MINGW64 ~/Desktop
$ sed 's/123//g' 2.txt
abc
  eee
def
456


Administrator@PC-20180827UNGA MINGW64 ~/Desktop
$ sed '/123/d' 2.txt
abc
def
456

sed  's/123/hello/'   1.txt   #将文件中的123替换为hello,默认只替换每行第一个123
sed  's/123/hello/g'  1.txt #将文本中所有的123都替换为hello
sed  's/123/hello/2'   1.txt  #将每行中第二个匹配的123替换为hello

$ sed 's/^[0-9]/(&)/' 2.txt #将每一行中行首的数字加上一个小括号   (^[0-9])表示行首是数字,&符号代表匹配的内容
abc
(1)23 123 eee
def
(4)56
(1)23
$ sed -r 's/(^[0-9])/(\1)/' 2.txt 		#	-r或者-E表示使用扩展正则
abc
(1)23 123 eee
def
(4)56
(1)23

sed  's/$/&  'haha'/'  1.txt   # 在1.txt文件的每一行后面加上"haha"字段

对一行模式多次:
	1、用-e
	2、在‘’中用;隔离模式
匹配多行,模式用,分割
	sed  '/123/,+1d'  1.txt   #删除匹配123的行及其后面一行
	sed  '/123/,$d'  1.txt    #删除从匹配123的行到最后一行
    sed  '1,/123/d'  1.txt    #

webshell

有没有代码实现的webshell呢?可以在浏览器上打开网页??我找了好久,都没有我想要的。。。奈何我太菜。
docker的butterfly看着挺舒服的,docker run -d -p 57575:57575 garland/butterfly 如下:
在这里插入图片描述
我好像用java实现一个可以在网页打开的shell终端。如何实现。。。。websocket??

shell 冒泡排序

#!/bin/bash 
function bubbleSort(){
  local arr=($1)
  local len=${#arr[@]} 
  for ((i=${len}; i>1; --i)){
	for ((j=1; j < i; ++j)){
		if [[ ${arr[${j} - 1]} -gt ${arr[${j}]} ]];then
			local temp=${arr[${j} - 1]}
			arr[${j} - 1]=${arr[${j}]}
			arr[${j}]=${temp}
		fi
	}
  } 
  echo "${arr[*]}"
}
 
regions=(9 1 4 3)
sd=$(bubbleSort "${regions[*]}")
echo ${sd[@]}

shell的script命令

这个命令还挺好用的
比如你想录制一下在命令行敲的所有命令和结果
那么

script res.txt
正常敲你的命令
ctrl + d

所有的命令和结果都会在res.txt文件中

shell的并行

肯定使用子shell了

# 子shell
sub_command &
#子shell的pid
sub_pid=$!
# 父shell做什么事
do_some
# 等待子shell完成
wait $sub_pid

組命令

{ echo RRR; ls; pwd; echo “ss”; } | sed ***

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值