前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >shell 学习笔记(16)

shell 学习笔记(16)

作者头像
用户1177713
发布2018-02-24 10:35:22
1.4K0
发布2018-02-24 10:35:22
举报
文章被收录于专栏:数据之美数据之美

转载请注明出处: https://cloud.tencent.com/developer/user/1177713/activities

注:以前的1-15连载部分放在百度空间,

目前百度空间已不支持博客搜索,

但你可以使用google搜索关键词:

leejun_2005 shell学习笔记

代码语言:javascript
复制
1501.巧用bash的{}扩展备份目录:
        cp file.txt{,.bak}
1502.利用at执行一次性命令:
        echo "ls -l" | at midnight		#Execute a command at a given time
1503.kill -1 或者 kill -HUP 一般用来重新读取配置文件:(一般程序自己实现的)
        HUP 其实就是给个信号,你的程序可以根据这个信号做一些事情,比如reload进程,或者是rotota日志。例如 squid、Nginx、xinetd。
        kill就是发送一个信号,而各种信号一般都有默认的意义,但是各个软件不一样。比如ping在遇到3信号的时候就会输出统计。
        nohup,就是对应的这个信号 HUP。
1504.Read-only file system:文件系统只读
        如果/data在/分区上:mount -o remount /data,其实/分区也可以remount的,只是不能umount	
        原因:磁盘io很高、硬盘挂掉、死机等
        mount -o remount,rw /data			rw好像是预设值,既然有nodiratimne,加上noatime吧
1505.巧用正则的匹配位置 RSTART 和匹配长度 RLENGTH 寻找子串:
        $ echo 'QWADGDABCfooDGJDJLGJWLJABCbarGLDABCwhyJGKABCkkJGJKDJGLABCtnndJDK'|、
        awk '{while(match($0,/ABC/)){print substr($0,RSTART);$0=substr($0,RSTART+RLENGTH)}}'
1506.多次调用 -k 实现多次排序:
        sort -t' ' -k3.3 -k1,1  #sort -k中的.表示按指定域中的第几个字符来排序
1507.重启网络用sudo /etc/init.d/networking restart,或者ifdown eth0 ifup eth0,注意要一起执行,否则你网络就断了。
1508.二进制文件编辑不要用vi,你保存后会在最后加换行,会破坏这个文件。vi会检查文件,如果没换行,会加上,二进制文件最后一般都没换行的。
        你复制个/bin/ls,用vi打开,什么都不做,保存,wc -c看下,多一个字符。
1509.EOF 不是字符,EOF是个信号,告诉程序没了。
1510.保留相邻重复行:
        echo "aaa
        1111
        1111
        1111
        aaa"|awk 'a[$1]&&NR!=a[$1]+1{next}{a[$1]=NR}1'
1511.man cat出现 ^H 字符:
        man cat |col -b > cat-help	:^H是高亮显示用的
        echo 'a^Ha'|less,a就高亮了,^H是按ctrl+v,再ctrl+h输入的
        BTW:为何退格出现 ^H :打字机时代,要加亮一个字符,操作方法是敲一次字符,回退,然后再重复敲一遍。(见维基百科)
1512.IFS设为换行符:IFS=$'\n'  
1513.利用 find -prune 限制查找多个目录:
        find / \( -path /root/decli -o -path /data/robinechen -o -path /data/yunwei \)  -prune   -o -type f -name "*vim*"  -print
1514.巧用逻辑操作打印 rm 的报错状态:
        rm a || echo error &
        rm a & ; [ $? -ne 0 ] && echo error  # 实际上即使 rm a 出错,也不能打印出 error
1515.巧设RS合并行:
        echo "1111
        33\n
        5555" | awk -v RS='\\\\n\n' -v ORS="" 1
        awk -v RS='\0' -F'\\\\n\n' '{for(i=1;i<=NF;i++){printf $i}}'
1516.获取进程列表及进程路径:
        netstat -nlp|awk -F '[ ]+|/' 'NR>2{if($0 ~/Active UNIX/){exit};res=gensub(".* +([0-9]+)/[^/]+","\\1",1,$0);a[res]}END{for(i in a){print i}}'|xargs -I {} ls -l /proc/{}|grep -E 'exe|cwd'|awk '{print}NR%2==0{print ""}'
1517.cut 也有输出分隔符:
        echo '1 3 5' | cut -f1-3 -d' ' --output-delimiter=o
1518.delete和backspace都无效:reset 或者 stty  cooked 试试
1519.linux下创建 dvd ISO 镜像:
        dd if=/dev/cdrom of=~/cdimage.iso
1520.利用bash转义改变grep搜索颜色:
        echo $'\e'[31m; grep "$1" aaa; echo $'\e'[37m
1521.打印第2行到倒数第2行:sed '1d;$d'	
1522.关于 kill -9 进程杀不掉:
        ps -eo stat,pid,cmd|grep httpd,看下进程状态
        都D了,通常是IO导致的深度睡眠,lsof看下在干嘛,
        kill -9也杀不掉?恩,D和Z都是-9杀不掉的,D只能等io结束。
1523.seq -s 设置序列分隔符:
        seq -s, 9   #echo {1..9},|sed 's/,$\| //g'
        seq -s, 9 |awk '{for(i=1;i<=9;i++)print gensub(i,"null",1,$0)}'
1524.通过多次的幂运算将CPU迅速撑到 100%:
        while :;do echo 2^2^20|bc &>/dev/null ;done   # 多核的话需要起多个进程丢到后台
1525.linux下如何打印出指定进程的进程树,而不是pstree打印全部的:pstree -ps pid
1526.sort 如果用-k指定了的话,那么n就要后置,如 sort -k2,3 -k1rn
1527.paste 把标准输入按列拼接成行:
        seq 20 |paste - - - - -			# xargs -n5
        注意:不同于多个输入:paste <(seq 3) <(seq 3 5)
1528.expect 在send密码之前有些系统需要 sleep 一下或者 set timeout=-1,否则导致密码在提示之前捕获而报错,可以expect -d 调试下
1529.删除 windows 下的 ^M 回车换行符:
        tr -d '[:cntrl:]'  ; dos2unix;tr -d \\r;sed -i '/^M/d' # ctrl -v -M
1530.统计文件夹大小:
        du -hx --max=1 ; du -sk ;du -hsc
1531.关于shell/awk的随机数:
        随机数伪随机,是根据随机种子计算出来的,随机种子确定,随机数就确定。
        awk的随机种子默认是当天的天数。那怎么修改这个随即种子?srand()
        一般用纳秒做随机种子,不过好像awk只能获取到秒,就是同一秒执行的话随机数还是一样的。
        随机数是可能有重复的,因为是随机产生的。
1532.一个文件末尾没有换行符,怎么加个换行符:$'\n'
        tail -c -1判断,如果不是换行,就echo >>加一个,
        或者你这样,先echo >>,然后在去掉空行,这样就不用判断了
        很多windows编辑软件会很“贴心”得去除文件最后一个换行,vim是会很贴心的加上最后一个换行,除非是空文件,不动。
1533.关于shell解析一次,awk再解析一次转义符的例子:
        awk 'BEGIN{print "\\("}'		# 双引号内的\\( 被shell解析了一个
        \(
        echo "1(2)3"|awk -F '\\(2' '{print $2}'   # ( 不转义是组合
        )3
        awk "BEGIN{print '1'}"			# awk以单引号为分隔符,所以里面不能用单引号。除非你用""去掉单引号的作用,就像shell下一样
        awk:             ^ invalid char ''' in expression
1534.巧用 RS、RT 匹配双引号段,去掉非双引号空格:
        echo 'abc   234   fsdfds 555 "34   666    53242 " asaf    tttttt'|awk -vRS='"[^"]+"' '{gsub(/ +/," ");printf $0 RT}'
        abc 234 fsdfds 555 "34   666    53242 " asaf tttttt				# 注意双引号要偶数个出现,RT 会针对每一行进行动态变化。
1535.base64 的编码与解码:base64 -d <<<anVuZV8xMjAxQHFxLmNvbQo=
1536.用find 找到几千个文件,然后想用 xargs 结合 tar打包,为什么tar包里面只有部分数据:
        xargs --show-limits看下,如果你的命令超过命令行长度限制,会自动切分,用tar -r,这样就好了
1537.rsync 显示远端服务器目录列表:rsync -avz dst
1538.linux 下 .so文件找不到 一般是ld的cache目录没更新,执行了一下ldconfig,就正常了。
1539.变量不加双引号在某些特定情况下被解析为 IFS 而显示为空:
        a="";echo $a|xxd	;a=$'\n';echo $a|xxd	;a=" ";echo $a|xxd
        空格和\n都是IFS,所以echo $a=echo, 所以要用"$a",因为不加双引号,空格被认为是IFS,跳过,因为只有零个参数,所以结果就是空
1540.用 read -N1 捕获 回车符 \n:
        read -N3 a
        echo "$a" && echo "$a"|xxd
1541.sed 中行范围扩展匹配:
        seq 10| sed -e{3,4,5,10}'s/.*/--/'  	#行范围不固定的扩展匹配
1542.sort -g 把科学计数法按普通数字排序
1543.删除乱码:LANG=C tr '[:punct:]' 123
1544.seq 等宽并指定分隔符: seq -w -s, 0 299 
        用echo 或者 for((i=1000;i<=1229;i++)); do echo ${i:-3}; done  或者 printf 格式化
1545.sort -k n.m 按某列字符排序:sort  -k 1.1,1.1  -k 1.2n  #第一列按字典排,第二列之后按数字排
1546.shell变量为了防止 word split,需要加上引号:
        june@~ 00:42:25>
        a=`echo -e "1\n2"` && echo $a
        1 2
        june@~ 00:58:38>
        echo "$a"
        1
        2
        june@~ 00:58:42>
1547.找出bash数组是否有元素“匹配”(不是存在)给定字符串:
        a=(1 2 3 abc) && [[ "${a[@]}" =~ 'ab' ]] && echo '------match'			# 也可以用 grep -q
1548.合并前两列:sed -r 's/\s+//'
1549.awk的asorti 是把下标按字典排序,可以得到新的下标数组与数组长度,二次引用即可获取原数组 value
        awk '{n=$1;getline;h[n]=h[n]"\n"$1}END{n=asorti(h,s);for(c=1;c<=n;c++)print s[c]":"h[s[c]]"\n=="}'
        要数字排序需要把下标拿出来用 asort 函数,然后进行二次引用
1550.awk 跨行匹配,并用gsub替换返回匹配次数:
        awk '{$0=n$0;c+=gsub(/China/,"");n=$NF}END{print c}' 1.text
1551.grep -A -B实现连续多行匹配:
        seq 3|grep -A1 1|grep -B1 ^2
        awk -vk1="abc" -vk2="efg" '{c++}$0~k1"$"{c++;getline n;if(match(n,"^"k2))print c-1":"$0"\n"c":"n}' filename 
1552.关于 crontab 的星期和 月日的 and or 关系:
        30 3 * * 1 dosomething , 是每周一3点半执行是确信无疑的了。
        30 3 1 * 1 dosomething , 是当1号是周一的时候执行吗?不是!是1号,或者周一的时候执行。
        crontab中的星期和日、月是一个“或”的概念,而非“和”的概念。
1553.awk、sed的缓冲问题:
        man awk	:fflush([file]) 		#awk 不是,与系统缓存与文件大小有关。
        man sed	:-u, --unbuffered		#sed 是因为他是行缓冲方式,遇到换行就会输出。
1554.sed N P D 的解释:
        首先;你加了-n参数,不会默认输出pattern space里的内容,只有p或者P操作才会打印,你先清楚这点.
        当第一行的时候,N读取下一行,注意这时候的行号已经是2了,PS里的内容是 1\n2;
        因为不是第4行,所以不执行{ } 里的操作,执行完毕,因为-n参数不会输出PS里的内容.
        这时候继续执行,已经是第三行了,因为第二行读走了,N操作,PS里的内容是3\n4,这时候行号是4,
        满足4{P;D}条件,执行P,请查阅sed资料,P是打印PS里第一行的内容,那就是3输出到了屏幕.
1555.cp mv rm,默认都是不提示,加-i才提示,这三个命令的-f参数都不一样,好好看看。
        23:57:29#tp#~> rm -f addsf
        23:57:36#tp#~> rm -f addsf
        23:57:37#tp#~> rm addsf
        rm: 无法删除"addsf": 没有那个文件或目录
        23:57:39#tp#~> rm -i addsf
        rm: 无法删除"addsf": 没有那个文件或目录
        23:57:42#tp#~> 
        rm -f是不提示不存在的文件,rm 默认就是不提示是否删除,加上-i才是提示是否删除
1556.awk的精度问题:
        awk 'BEGIN{print OFMT;print 1335533180.170077-1335533180.169424;OFMT="%f";print OFMT;print 1335533180.170077-1335533180.169424}'
        %.6g
        0.000653028
        %f
        0.000653
1557.head 和 tail 的正负数既可表示开头也可表示取到结尾xx处:
        head -c -2  	# 除去一个文件的最后两个字节,也可以 dd 或者 sed '$s/..$//'
1558.查看文件以回车换行结尾:set fileformat 或者 xxd
        换行符 \n ^j 0a LF
        回车符 \r ^M 0d CR
        如果是mac,用回车做换行符,那么你直接cat是看不到换行的。	
1559.awk 索引index asorti 是按字典排序,因此如果数字的话以对齐位数后再排序:
        a[sprintf("%03d",$n)]
1560.curl -G 模拟 post/get 请求(默认是 post 方式),--data-urlencode 进行 urlencode 编码
        curl -v -L -G --data-urlencode '我们' http://www.baidu.com/s
        curl -v -L -G -d "lat=41.225&lon=-73.1" http://localhost:5000/pulse		# by default, calls POST. If you want to send a GET request,use -G
1561.urlencode 编码的其它几种方式:
        echo '手机' | tr -d '\n' | xxd -plain | sed 's/\(..\)/%\1/g'		# 这里用到了 xxd,python的话有API可以直接调用
1562.urldecode 编码解码:
        printf $(echo -n "http://www.baidu.com/s?wd=%ca%d6%bb%fa" | sed 's/\\/\\\\/g;s/\(%\)\([0-9a-fA-F][0-9a-fA-F]\)/\\x\2/g')"\n"
1563.stat 查看数字权限:
        stat -c %a 
1564.gzip 查看文件压缩完成时间:缺省情况下gzip会保留源文件的时间戳, 所以是查不到你想要的完成时间的
        ls -lctr yourfile.gz		或者    gzip -c foo > foo.gz
1565.cat -v 编码:
        21:44:47#tp#~> echo 中|xxd
        0000000: e4b8 ad0a                                ....
        21:49:36#tp#~> echo 中|cat -A
        M-dM-8M--$
        21:49:39#tp#~>
        d的十六进制是64,8的十六进制是38,-的十六进制是2d  
        V的十六进制是56,P的十六进制是50。  
        其实就是系统的一种对应关系,中文在ascii里面没有,所以就这样表示了  
1566.man的相关用法:
        man 5 crontab		# 关于 crontab 的日期介绍
        man不只是有1个,有1-8。man -a crontab	就查全部 man 文档了.	man -f crontab,看有哪些帮助文档
        man -a crontab,会一个一个man看过去,你按q以后进入下一个man 		# man man
1567.rsync复制原理:
        rsync 会在命令运行的初始阶段产生一个hash列表,里面列出所有要同步的文件和目录。 如果文件的大小在复制后有改变,
        那么rsync 会尝试重新复制,几次尝试后,如果还是不一致,就会报个错。
1568.test -n/[ -n ] 问题:
        在[  ]中, 如果只有一个参数, 那这个参数就被当成一个普通的字符串,并用 -n 测试其长度, 
        比如, [  -gt  ],  相当于 [ -n -gt ],因此注意下面两者区别:
        [ -n "" ];echo $?			; 			  [ -n ];echo $?
1569.SIGNKILL(9) 和 SIGNTERM(15) 的区别在于:
        SIGNKILL(9) 的效果是立即杀死进程. 该信号不能被阻塞, 处理和忽略。
        SIGNTERM(15) 的效果是正常退出进程,退出前可以被阻塞或回调处理。并且它是Linux缺省的程序中断信号。
1570.sort排序会用到临时文件:默认 tmp 空间不足会报错:
        sort: write failed: /tmp/xxxxx: No space left on device
        linux的指定 -T 参数修改目录或者修改 TMPDIR变量
1571.printf ascii 与数字转换:
        echo "7249 81"|awk '{printf "%c %c\n",$1,$2}'			# 为什么结果一样?
        echo "7249 81"|awk '{printf "%x %x\n",$1,$2}' 
        1c51 51					# 高位被丢弃了
        echo "7249 81" | awk '{printf "%d %d\n",$1%256,$2}'
        echo '7249%128'|bc
1572.显示shell开启了哪些shell标志:
        $-     The current shell flags, such as -x and -v.
           -      Expands to the current option flags as specified upon invocation, by the set builtin command,  
           or  those set by the shell itself (such as the -i option).
           set [+abefhkmnptuvxBCEHPT] [+o option] [arg ...]
           echo $- && set -x && echo $- && set +x && echo $-
1573.top获取指定id的进程信息,-b 避免输出控制字符:
        top -p 25097 -n 1 -b|cat -A
1574.巧用gsub查找单词出现的次数:awk '{print $1,gsub("id","")}'
1575.脚本手动执行正常,crontab 无法执行:
        由于 crontab 不加载 profile, bashrc之类的环境变量,而这其中受的影响很大比例都是PATH变量
        所以养成好习惯:每个脚本之前就加上加载用户环境变量文件
1576.chattr 设置权限防止root删除:
        -rw-rw-rw- 1 root root 959301 May 15 15:40 .my_history
        gs_chatlog_2_207:/data # chmod 777 .my_history
        chmod: changing permissions of `.my_history': Operation not permitted
        gs_chatlog_2_207:/data # whoami
        root
        gs_chatlog_2_207:/data #
        lsattr .my_history  
        -----a------- .my_history			
        解除-a限制:chattr -a 文件名
1577.awk或perl利用时间戳获取上一天日期:
        perl -e 'use POSIX;print strftime("%Y%m%d",localtime(time-86400))'
        awk -vnum=-2 'BEGIN{print strftime("%Y%m%d",systime()+86400*num)}'
1578.删除所有的空文件:
        find . -maxdepth 1 -size 0c -delete
        find . -maxdepth 1 -empty -delete
1579.vim可以编辑 tar.gz, tgz, zip 等压缩文件:
        vim some-archive.tar.gz
1580.临时忽略 SSH host key:
        ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no username@host
        When you SSH to a server whose host key does not match the one stored in your local machine's known_hosts file, 
        you'll get a error like " WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!" that indicates a key mismatch.
        If you know the key has legitimately changed (like the server was reinstalled), 
        a permanent solution is to remove the stored key for that server in known_hosts.
1581.找出页面的最后修改时间:
        wget -S --spider http://osswin.sourceforge.net/ 2>&1 | grep Mod
        Last-Modified: Wed, 08 Feb 2012 20:14:53 GMT
        或者用 curl 替代:
        curl --head -s http://osswin.sourceforge.net | grep Mod
1582.先把整个文件的内容都显示出来然后再跟踪显示:tail -n+0 -f 
1583.find -L 查找链接对应目录:
        链接  /usr/local/my_lib  ->  /usr/lib/
        find -L /usr/local/my_lib -name "*so"
1584.关于 rsync 的服务端与客户端:
        1.1.1.1:/tmp是走的ssh
        1.1.1.1::/tmp和rsync://1.1.1.1/tmp是rsync服务端 
        但是很多配置是ssh不支持的,而且这样你要开帐号,还要开ssh的帐号
        否则直接虚拟帐号,比如debian啊什么的,开的rsync,难道把ssh帐号给你?
        走ssh的话其实就是scp的升级版,少点数据传输。
        rsync daemon 的话在 daemon 上控制权限,要开 daemon,ssh 的话 ssh 控制权限,要开ssh
1585.回车与换行符的终端输出:
        ^J \n 0A 换行符
        ^M \r 0D 回车符
1586.BREs, EREs是否支持\s(PREs)和sed是否支持\s没有必然联系, 没规定软件不能扩展自己的匹配方法。	
1587.获取文件的绝对路径:realpath filename			# 也可以 pwd + "/" + filename
1588.tar.gz 不能直接 -r, 要先解压成 tar,再-r,最后再压缩成 tar.gz 
1589.vim 列模式:
        将光标放在需要选择列的第一个字符上,在一般模式中,按下“Ctrl+v”,
        然后使用“↓”或“↑”进行块字符的选择,选中的地方会反白显示,
        可以使用使用“y”进行复制,“p”进行粘贴,“d”进行删除操作。
        或者:
        Ctrl-V 选块,然后shift-i,shift-a或者c,x进行改写操作。双击 Esc 退出确认生效。
1590.read读取标准输入的问题:
         while :	# 此时 while循环里的块 FD0 已经被 <filename.txt 覆盖,类似局部变量优于全局变量
        	read	# read要读入标准输入可以 read var <&1 或者 read var </dev/tty
         done < filename.txt
1591.tcpdump -s0 不限制包长度 抓包:
        tcpdump -s0 -w a.pcap host 8.8.8.8 and tcp port 80,然后a.pcap传到本地,用wireshark打开。# wireshark 可以认为是 tcpdump的图形界面
1592.覆盖文件需要对文件有w权限,删除需要对文件所在目录有w权限,而不需要对文件有w权限:
        一个目录里面有多少文件都是记录在目录项里的。只要让这个目录不包含某个文件,就相当于删除这个文件了。
        所以删文件的实质是:使其所在的目录不再包含这个文件。所以对目录有写权限就行了。
1593.巧用 !* 匹配单词边界,实现单词字符分割:
        sed 's/!*/ /g' <<< 'ab1c2pha'		# 非任意字符,即为单词边界,等价于 sed 's/\B/ /g' <<< 'ab1c2pha'
        echo "ab1c2pha" |sed 's/./& /g'			# sed 's/\w/& /g'
        awk -vFS="" '{$1=$1}1' <<< ab1c2pha
1594.用printf输出一行终端字符:
        printf "%$(tput cols)s\n"|tr ' ' '='
1595.查看某个进程加载的环境变量信息:
        tr \\0 \\n </proc/$pidxxxxx/environ
        或者如果 unix、freebsd 没有 environ,那就试试下面的: 
        cmdpid=`pidof cmd` && ps eww -p $cmdpid
1596.grep -l 实现打印匹配字符串的文件名,匹配并立即退出下一个,awk 的 exit 或者 nextfile 也可以实现。
1597.将多行变成一行的几种方法:
        tr、xargs -n1、awk NF+=0 ORS=" "、echo $(<file)			# paste -s  或者 column 也行
1598.每两行合并为一行:
        sed '$!N;s/\n/ /' urfile
        awk '{printf (NR%2)?$0 FS:$0"\n"}' urfile
        paste -s -d ' \n' urfile		# -d 后面的分隔符是个 list
        xargs -n2 < infile
1599.shell下的8进制转码问题:
        14:26:38#tp#~> echo $'\270\264\274\376'
        复件
        14:26:55#tp#~> 
        这个也可以,我现在把终端编码换到gbk了,就不用iconv了
        14:21:17#tp#~> awk  'BEGIN{print "\270\264\274\376"}'|iconv -f gbk -t utf-8
        复件
        14:21:24#tp#~>  # 直接 echo转不了,这里awk把\270\264转换成汉字 ,iconv是转换编码
        echo -e '\0270\0264\0274\0376'也可以
        不过还是echo $'\270\264\274\376'方便,不然还要每个\都加个0。# echo $'' 相当于 echo -e ''
        按理说八进制都0开头确实比较好 不过现在好多都可以去掉0 不懂为什么这么不和谐。 
        bash 3.00.15确实是这样的,后来的bash改掉了,不用加 0 了。
        其实 python -c 'print "\270\264\274\376"' 也行。
1600.xargs -d 支持分隔符:
        echo "abc,dd,bach,dong,jing,shang,china,bejing" | xargs -d, -n1
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档