Linux shell 学习是一个循序渐进的过程。最开始我是通过《鸟哥的linux私房菜》学习Linux的同时学习了 shell, 入门之后就一直是遇到问题、搜索问题、总结问题的学习过程。
后来感觉一些不错的命令,汇总起来方便后续的查找,于是慢慢的积累了几十条常用的命令,取之于网络,用之于网络,希望对大家有所帮助!
一、删除换行符
cat 文件名|tr -d '\n'cat 文件名|tr -d '\r' #可以删除"^M"
cat 文件名|sed ':1;N;s/\n//;t1' 【使用sed删除换行】
二、将linux文件中的tab更换为空格的三种方法
1,用sed命令#sed ‘s/\t/ /g’ filename >filename1
2, 用tr命令
#cat filename|tr "\t" " " >filename2
3,用col -x命令
#cat filename|col -x >filename2
扩展阅读: http://blog.sina.com.cn/s/blog_53a173560101ao2p.html
将多个空格替换成逗号
head a.txt |sed 's/ \+/,/g' 【 + 需要转义】
head a.txt |sed 's/ */,/g' 【 * 表示0个或任意多个字符】
’+‘ 这是匹配前面的空格(\s)一次或者多次。 意义同 \s \s* 。
扩展阅读: http://bbs.linuxtone.org/thread-17848-1-1.html
三、通过开始行和结束行,查找指定数据
[ymm@EVERSEC temp]$ cat a.txt1 dirty data
2 dirty data
3 ======
4 I want these data
5 I want these data
6 ======
7 dirty data
8 dirty data
9 ======
10 I want these data
11 ======
[ymm@EVERSEC temp]$ sed -n '/======/,/======/p' a.txt
3 ======
4 I want these data
5 I want these data
6 ======
9 ======
10 I want these data
11 ======
[ymm@EVERSEC temp]$
sed -n '/开始字符串/,/结束字符串/p' 文件名
四、shell中的分组
[root@ tmp]# cat a.txta 200 123
a 12 32
a 32 3
b 1200 aaa
b 1 22
b 22 22
c 333 333
d 222 333
#分组求和
[root@ tmp]# cat a.txt |awk '{a[$1]+=$2}END{for(i in a)print i,a[i]}'
a 3
b 3
c 1
d 1
#统计数目
[root@ tmp]# cat a.txt |awk '{a[$1]++}END{for(i in a)print i,a[i]}'
a 244
b 1223
c 333
d 222
#分组求最大值
[root@ tmp]# cat a.txt |awk '{max[$1]=max[$1]>$2?max[$1]:$2}END{for(i in max)print i,max[i]}'
a 200
b 1200
c 333
d 222
#简单的按列求和
[linux@test /tmp]$ cat test
123.52
125.54
126.36
[linux@test /tmp]$ awk '{sum += $1};END {print sum}' test
375.42
扩展阅读: http://bbs.chinaunix.net/thread-1511070-1-1.html
http://www.5iops.com/html/2013/script_0418/267.html
http://www.linuxsong.org/2010/09/shell-column-sum/
五、查找包含某字符串的行及后续行
sed -n '/xxxx/{p;n;p}' a.log查找文件“a.log”中包含“xxxx”的行后续一行。n表示下一行,p表示打印。
六、grep的高级用法:
Context Line Control-A NUM, --after-context=NUM
Print NUM lines of trailing context after matching lines. Places a line containing a
group separator (--) between contiguous groups of matches. With the -o or
--only-matching option, this has no effect and a warning is given.
-B NUM, --before-context=NUM
Print NUM lines of leading context before matching lines. Places a line containing a
group separator (--) between contiguous groups of matches. With the -o or
--only-matching option, this has no effect and a warning is given.
-C NUM, -NUM, --context=NUM
Print NUM lines of output context. Places a line containing a group separator (--)
between contiguous groups of matches. With the -o or --only-matching option, this
has no effect and a warning is given.
-A NUM 显示包含的字符串和下面的NUM行数据
-B NUM 显示包含的字符串和上面的NUM行数据
-C NUM 显示包含的字符串及上面和下面的NUM行数据
七、指定文件大小和
使用"ls * |du -sh" 得到的结果其实是当前目录的总大小,如果希望得到指定文件的总大小,应该通过如下方式:[root@localhost tmp]# ls *txt |xargs du -csh
12K findex2txt
12K fwlog2txt
24K total
[root@localhost tmp]# ls *txt |xargs du -csh|grep total|cut -f1 #过滤得到文件总大小
24K
[root@localhost tmp]#
扩展阅读: http://blog.csdn.net/michaelpp/article/details/12998205
八、解压文件汇总
总结1、*.tar 用 tar –xvf 解压
2、*.gz 用 gzip -d或者gunzip 解压
3、*.tar.gz和*.tgz 用 tar –xzf 解压
4、*.bz2 用 bzip2 -d或者用bunzip2 解压
5、*.tar.bz2用tar –xjf 解压
6、*.Z 用 uncompress 解压
7、*.tar.Z 用tar –xZf 解压
8、*.rar 用 unrar e解压
9、*.zip 用 unzip 解压
扩展阅读: http://www.jb51.net/LINUXjishu/43356.html
九、sed插入空行
满足某种条件的前面插入插入空行[root@EVERSEC ~]# ymm="yangmingming"
[root@EVERSEC ~]# echo $ymm
yangmingming
[root@EVERSEC ~]# echo $ymm|sed "/yang/i\\"
yangmingming
[root@EVERSEC ~]# echo $ymm|sed '/yang/i\\'
yangmingming
[root@EVERSEC ~]#
扩展阅读: http://bbs.chinaunix.net/thread-4056672-1-1.html
十、获取除最后一列的其他列数据
NF代表:浏览记录的域的个数[root@EVERSEC in]# echo "yang ming ming" |awk 'NF--{print $0}'
yang ming
[root@EVERSEC in]# echo "yang,ming,ming" |awk 'NF--{print $0}'
[root@EVERSEC in]# echo "yang ming,ming" |awk 'NF--{print $0}'
yang
[root@EVERSEC in]# echo "yang ming,ming" |awk 'BEGIN{FS=OFS=","}NF--{print $0}'
yang ming
[root@EVERSEC in]# echo "yang ming,ming" |awk 'BEGIN{FS=OFS=","}NF--'
yang ming
[root@EVERSEC in]#
十一、检索异常的'\r'
cat *.txt |awk '/\r[^\n]/'注:需要排除结尾'\r\n'的情况
十二、打印文件的偶数行
sed '1d;n;d'sed -n 'n;p'
sed -n '0~2p'
awk '!(NR%2)'
awk 'i++%2'
awk '!(i=i?0:1)'
awk '!(i=!i)'
扩展阅读: http://www.dewen.io/q/797/怎样用shell命令输出日志文件内偶数行?
十三、一行数据拆分成数组
awk 'BEGIN{
i=1
}
{
n = split($0, a, "|" );
while(i<=n){
print a[i];
i++;
}
}'
十四、sed正则表示式支持
-r, --regexp-extendeduse extended regular expressions in the script.
[root@EVERSEC tmp]# cat -n a.txt
1 yang|ming
2 yang
3 ming
[root@EVERSEC tmp]# cat -n a.txt |sed -n '/yang|ming/p'
1 yang|ming
[root@EVERSEC tmp]# cat -n a.txt |sed -r -n '/yang|ming/p'
1 yang|ming
2 yang
3 ming
[root@EVERSEC tmp]#
十五、删除异常“M-BM- ”字符
使用vim中的“set list”显示的都是空格,但是,使用cat查看的结果是“M-BM- ”[root@EVERSEC tmp]# cat a.txt
function a_sub {
sleep 3
}
[root@EVERSEC tmp]# cat -A a.txt
functionM-BM- a_subM-BM- {$
sleepM-BM- 3$
}$
[root@EVERSEC tmp]#
[root@EVERSEC tmp]# hexdump -C a.txt
00000000 66 75 6e 63 74 69 6f 6e c2 a0 61 5f 73 75 62 c2 |function..a_sub.|
00000010 a0 7b 0a 20 20 73 6c 65 65 70 c2 a0 33 0a 7d 0a |.{. sleep..3.}.|
00000020
""对应的空格,可以在word中通过输入"Ctrl+Shift+Space"输入,对应的十六进制为"0xc2 0xa0",所以可以通过sed的方式删除,如下:
[root@EVERSEC tmp]# sed 's/\xc2\xa0/ /g' a.txt |cat -A
function a_sub {$
sleep 3$
}$
[root@EVERSEC tmp]#
扩展阅读: http://askubuntu.com/questions/357248/how-to-remove-special-m-bm-character-with-sed
十六、IP的正则表示
"[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}"十七、获取最后两列数据
awk 'NR>1{print $(NF-1),$NF}'扩展阅读: http://bbs.chinaunix.net/thread-706390-1-1.html
十八、多行数据合并成一行
tr -s "\n" " " < test.txt;echo扩展阅读: http://blog.sina.com.cn/s/blog_4a3c301c0100lqbm.html
十九、shell字符串分割成数组
a="one,two,three,four"OLD_IFS="$IFS"
IFS=","
arr=($a)
IFS="$OLD_IFS"
for s in ${arr[@]}
do
echo "$s"
done
arr=($a)用于将字符串$a分割到数组$arr ${arr[0]} ${arr[1]} ... 分别存储分割后的数组第1 2 ... 项 ,${arr[@]}存储整个数组。变量$IFS存储着分隔符,这里我们将其设为逗号 "," OLD_IFS用于备份默认的分隔符,使用完后将之恢复默认。
附加:修改IFS之后,如果希望打印原始的行,需要恢复原始的IFS,不然打印的数据之间会包含空格
a="one,two,three,four"
OLD_IFS="$IFS"
IFS=","
echo $a
IFS="$OLD_IFS"
echo $a
one two three four
one,two,three,four
附加:如果希望使用while循环获取文件中的每一行数据,那么需要修改IFS为换行符,不然,文件内部的空格或者Tab键也会分割字符串。
使用方法【注意使用了"$",并且只能使用单引号】:
IFS=$'\n'
扩展阅读: http://1985wanggang.blog.163.com/blog/static/776383320121745626320/
二十、获取 Shell 脚本自身进程 pid
这里涉及两个指令: 1. $$ :当前 Shell 进程的 pid 2. $! :上一个后台进程的 pid 可以使用这两个指令来获取相应的进程 pid。例如,如果需要获取某个正在执行的进程的 pid(并写入指定的文件):myCommand && pid=$!
myCommand & echo $! >/path/to/pid.file
注意,在脚本中执行 $! 只会显示子 Shell 的后台进程 pid,如果子 Shell 先前没有启动后台进程,则没有输出。
扩展阅读: http://weyo.me/pages/techs/linux-get-pid/
二十一、获取程序的启动时间和运行时间
ps -eo lstart 启动时间ps -eo etime 运行多长时间.
ps -eo pid,lstart,etime|grep pid
例:ps -eo pid,lstart,etime|grep 4559
显示进程id、启动时间、运行时间、命令,便于通过grep过滤
ps -eo pid,lstart,etime,cmd|grep vim
二十二、awk按照多分隔符分割字符串
awk -F"[@ /t]" '{print $2,$3}' test以@,空格,Tab键分割test文件的每一行,并输出第二、第三列。
如果希望使用“[]”作为分隔符的话,可以使用下面的方式
awk -F"[][]" '{print $2,$3}' test
扩展阅读: http://blog.csdn.net/hongchangfirst/article/details/25071937
awk默认的分隔符包含一个和多个空格,如果设置多个分隔符的时候,中括号中间的一个空格只能识别出一个空格,如果是多个空格的情况,会认为是多个分隔符,解决办法是让分隔符识别多个空格的情况:
awk -F"[@ /t]+" '{print $2,$3}' test
扩展阅读: http://bbs.51cto.com/thread-1126595-1.html
二十三、ls -l显示年与日时分秒等信息
ls -l --time-style="+%Y-%m-%d %H:%M:%S"扩展阅读: http://blog.itpub.net/10640532/viewspace-697496/
二十四、控制台显示红色闪烁的文字
echo -e "\033[37;31;5m yangmingming \033[39;49;0m"二十五、选择特定位数的字符
选择第四位到第七位[root@EVERSEC in]# echo "yangmingming"|cut -c 4-7
gmin
[root@EVERSEC in]#
二十六、grep比较两个文件的异同
1、统计两个文本文件的相同行grep -Ff file1 file2
2、统计file2中有,file1中没有的行
grep -vFf file2 file1
扩展阅读: http://hxl2009.blog.51cto.com/779549/677226
二十七、awk根据条件输出到不同文件
cat file.AVL|awk -F "|" '{if($19 == 0) print $0 >"ymm_0.txt"; else if($19 == 5) print $0 > "ymm_5.txt"}'扩展阅读: http://bbs.chinaunix.net/thread-538971-1-1.html
awk引用外部变量参见:
二十八、vim删除空行或者注释
删除空行:g/^$/d
删除空行以及只有空格的行
:g/^\s*$/d
删除以 # 开头或 空格# 或 tab#开头的行
:g/^\s*#/d
扩展阅读: http://www.cnblogs.com/carbon3/p/5915282.html
二十九、sed查找符合条件的记录进行字符替换
crontab删除自启动脚本前面的“#”,例如:#*/1 * * * * /etc/eversec/broadband-match/broadband-match-cron.sh
使用sed命令进行替换
sed -i 's/源字符串/目的字符串/g' /var/spool/cron/root
因为路径中包含'/',所以需要转义【转义试了下,麻烦并且没有成功,附加:后来验证是因为*没有转义导致】
网上说可以使用其他字符替换,例如:
sed -i 's:源字符串:目的字符串:g' /var/spool/cron/root【没有成功,附加:后来验证是因为*没有转义导致】
扩展阅读: http://bbs.chinaunix.net/thread-287191-1-1.html
后来发现了一个更好的办法:
sed -i '/broadband-match-cron.sh/s/^#//g' /var/spool/cron/root
先通过查找命令查找指定行,然后删除最前面的“#”,问题搞定。
附加:后来验证可行的笨办法
[root@EVERSEC in]# crontab -l|grep broadband-match-cron.sh
#*/1 * * * * /etc/eversec/broadband-match/broadband-match-cron.sh
#方法一:"/"转义
[root@EVERSEC in]# crontab -l|grep broadband-match-cron.sh|sed 's/#\*\/1 \* \* \* \* \/etc\/eversec\/broadband-match\/broadband-match-cron.sh/\*\/1 \* \* \* \* \/etc\/eversec\/broadband-match\/broadband-match-cron.sh/g'
*/1 * * * * /etc/eversec/broadband-match/broadband-match-cron.sh
#方法二:替换为%
[root@EVERSEC in]# crontab -l|grep broadband-match-cron.sh|sed 's%#\*/1 \* \* \* \* /etc/eversec/broadband-match/broadband-match-cron.sh%\*/1 \* \* \* \* /etc/eversec/broadband-match/broadband-match-cron.sh%g'
*/1 * * * * /etc/eversec/broadband-match/broadband-match-cron.sh
[root@EVERSEC in]#
三十、指定多行合并成一行
[root@EVERSEC match]# cat a.log192.168.1.17
down
192.168.1.103
open
[root@EVERSEC match]# cat a.log |awk '{if(NR%2 == 0) print $0; else printf("%s ", $0)}'
192.168.1.17 down
192.168.1.103 open
[root@EVERSEC match]#
或者:
[root@EVERSEC match]# cat a.log |awk '{if(NR%2 == 0) ORS="\n"; else ORS=" "; print $0}'
192.168.1.17 down
192.168.1.103 open
[root@EVERSEC match]#
扩展阅读: http://www.linuxidc.com/Linux/2013-11/92231.htm
三十一、一句话shell
xargs中的{}也可以和其他字符一起拼成新的字符串使用,cut的用法,也可以去掉最后一个后缀[root@localhost tmp]# for i in $(seq 1 3); do touch ymm_$i.txt.tmp; done
[root@localhost tmp]# ls ymm_*
ymm_1.txt.tmp ymm_2.txt.tmp ymm_3.txt.tmp
#cut可以截取出指定部分
[root@localhost tmp]# ls ymm_1.txt.tmp |cut -d"." -f1,2
ymm_1.txt
[root@localhost tmp]#
#处理文件
[root@localhost tmp]# ls ymm_*.txt.tmp|cut -d"." -f1,2|xargs -I {} echo {}.tmp {}
ymm_1.txt.tmp ymm_1.txt
ymm_2.txt.tmp ymm_2.txt
ymm_3.txt.tmp ymm_3.txt
[root@localhost tmp]#
如果文件数目太多的话,xargs可以添加-n1,表示没获取一个文件,就进行处理
xargs -n 1
删除文件的时候,就是因为文件数目太多,直接rm的时候,提示参数太长,所以,通过xargs搭配rm删除文件时,可以指定-n N
三十二、获取公网ip
curl members.3322.org/dyndns/getip扩展阅读: http://jingyan.baidu.com/article/3c343ff7e2b6830d3779632f.html
三十三、for循环中有空格的处理方式
[root@EVERSEC ~]# cat a.txtaa bb
cc dd
[root@EVERSEC ~]# for i in $(cat a.txt )
> do
> echo "--$i"
> done
--aa
--bb
--cc
--dd
默认情况下,空格也会作为分隔符
修改方式:
1. 修改分隔符为\n,注,赋值的时候,需要使用单引号
[root@EVERSEC ~]# OLDIFS="$IFS"
[root@EVERSEC ~]# IFS=$'\n'
[root@EVERSEC ~]# for i in $(cat a.txt ); do echo "--$i"; done
--aa bb
--cc dd
[root@EVERSEC ~]# IFS="$OLDIFS"
2. 通过while read line的方式
[root@EVERSEC ~]# cat a.txt |while read line; do echo --$line; done
--aa bb
--cc dd
[root@EVERSEC ~]#
如果是单个txt文件的话,使用下面的方式
while read line;do echo $line; done << file.txt
但是,倘若文件是多个文件,或者压缩的文件,亦或者过滤处理后的文件的操作,上述办法就不可行了。对应的解决方案就是
cat file.txt|grep something |while read line; do echo $line; done
三十四、vim替换引用
vim替换的时候,应用操作:%s/^\([0-9]\.[0-9].[0-9]\)/### \1/g
:%s/^\([0-9]\.[0-9]\)/## \1/g
:%s/^\([0-9]\)/# \1/g
在正规表达式中使用 \( 和 \) 符号括起正规表达式,即可在后面使用\1、\2 等变量来访问 \( 和 \) 中的内容。
扩展阅读: http://blog.csdn.net/hitlion2008/article/details/7964811
http://www.cnblogs.com/xuxm2007/p/3566855.html
把空格替换为换行
:% s/ /\r/g
扩展阅读: http://blog.csdn.net/tterminator/article/details/51610778
三十五、查找tab
其实在linux中要正确匹配tab(退格)符有两种方式1:用 grep $'\t' 你的文件
2:用 grep '按CTRL+V 键,再按TAB键' 你的文件
扩展阅读: http://www.linuxidc.com/Linux/2011-11/47000.htm