linux开发常用脚本,记录自己常用的一些 Linux Shell 脚本
常要在 Linux 下分析日志或其他類型的文件,基本用的命令也就 grep, awk, sed, cut, vim, cat, find, xargs, tail, more 或 less。本人工作平臺為 Mac OS X, 而 Mac 下的 grep, sed, awk 的行為與 Linux 下的 GNU 標準的相應命令是有差別的, 所以我總是在 Mac 下安裝 GNU 的 grep, sed, awk 等命令來替代系統默認的。
比如安裝下面的命令
$ brew install findutils gawk gnu-sed grep
以上會安裝 GNU 的 find, awk, sed 和 grep 命令,使用時要加個前綴,如 gfind, gawk, gsed 或 ggrep,也可以設置別名或符號鏈接來替換掉系統的相應命令。
注: brew install coreutils 會安裝眾多 Linux 下的基本命令替代品,ls, cat, cut 都在其中,使用它也是要加上前綴 g, 如 gls, gcut 等。
以下 grep, find, grep, sed 以 GNU 的行為為準。
grep?相關的命令
用了這么久的 grep, 反正它是用來查找字符串的,還能用正則表達式匹配。那么它的全名是什么呢?Global Regular Expression Print (GREP)。
高亮顯示匹配的字符串
這個效果很重要,不然顯示出了字符串還不清楚哪里匹配了,所以最好用個 alias
grep="grep --color=auto --exclude-dir={.bzr,CVS,.git,.hg,.svn}"
以下各種使用方式
$ cat planets.txt | grep -i e? ? ? # 忽略大小寫匹配
$ cat planets.txt | grep -e "[p|P]"? # 使用正則表達式匹配
$ cat planets.txt | grep -P -e "[p|P]{1,3}"? # 使用 Perl?風格正則表達式
搜索文件
$ grep -r --include "*.java" "print" src? ?# 從 src 目錄中的 *.java 中遞歸查找 print?字符串
輸出捕獲的分組
打印出匹配的字符串并不需總是要用 awk 分隔再打印,用 grep -oP 或 egrep -o 會更方便,如
$ echo 'employee_id=1234' | egrep -o '\d+'
1234
$ echo 'employee_id=1234' | grep -oP 'employee_id=\K(\d+)'? ? ? ? ? ? ? ? ? ? ? ?# Mac OS X 下可用? ?ggrep, P 為 Perl 正則表達式, \K 是 Perl 用來實現 look-behind, 如從 "=" 開始
1234
$ echo 'employee_id=1234' | grep -oP '(?<==)(\d+)'? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?# 另一種 lookbehind 方式, '(?<==)' 中的 ?<= 指定從后它后的的 =?號開始
1234
$ echo 'foo something bar' | grep -oP '(?<=foo )\w+(?= bar)'? ? ? ? ? ? ? ? ? ? ? ? # 用這個了理解一下 grep -P? Perl 的 look-behind 和 look-ahead
something
其他幾種輸出分組的方式
$ echo 'employee_id=1234' | sed 's/^.*employee_id=\([0-9]*\).*$/\1/'
1234
$ echo employee_id=1234 | sed -E 's/employee_id=([0-9]+)/\1/g'? ? ? ? ? ? ? ? ?# -E extended regex
1234
$ echo 'employee_id=1234' | awk -F= '{print $2}'
1234
$ foo='employee_id=1234'? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? # 以下是 bash?的方式
$ echo ${foo%%=*}
employee_id
$ echo ${foo#*=}
1234
控制臺的內容直接送到 vim?編輯器中
未打開 vim, 可用管道操作 xxx | vi - 如:
$ ls -l | grep py | vi -? ? ? # 這樣會打開 vim 編輯器,顯示 ls -l |grep py?命令的輸出內容
如果打開了 vim, 那么在 vim?中命令模式中輸入
: read !ls -l | grep py? ? ?# 就會在當前 vim 編輯器中添加 ls -l | grep py?命令的輸出內容
打開 vim 的同時打開語法高亮, 如果 ~/.vimrc 中已打開語法高亮,但 | vi - 沒有告知文件類型,所以需要 vim 啟動時加上 set syntax=json 或 set filetype=json
$ echo '{"age": 28}' | vi - -c 'set syn=json'? ? ? # 或者 set syntax=json, set filetype=json 或 set ft=json
$ echo '{"age": 18}' | vi -
也可以進入了 vim 后,在它的命令行下設置? :set syntax=json 或? :set filetype=json, 或簡單的用 :set syn=json 或 :set ft=json。
另外,假如用 vim 打開一個大文件,因為加載過多插件的因素滾動慢,可以用 vi -u NONE bigfile.json 來打開文件。
切分字符串
這也用到的命令就是 cut 或 awk,cut 能力比較弱,只能用單字符切割字符串,看如下幾個使用方式
$ echo "aa,bb,,cc:dd" | cut -d, -f1
aa? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?# -d 后指定用 , 號分隔,-f 輸出哪個字段
$ echo "aa,bb,,cc:dd" | cut -d, -f1 -f4? ?# 或者用 -f1,4
aa,cc:dd? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? # 輸出多個字段時又會用 -d 指定的分隔符連接
$ echo "aa,bb,,cc:dd" | cut -d, -f4 | cut -d: -f1
cc? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? #由于不支持模式分隔,所以要進行兩次切分
另一種方法就是用 awk 命令,awk 簡單是一個編程語言,它名字來源于它的三位作者的名字首字母(Aho, Weinberger and Kernighan), 不是 awkward 的意思。它的功能還是很強,我們且在這里看看怎么分隔字符串
$ echo "aa,bb,,cc:dd" | awk -F "(,*)|:" '{print NF,$1,$2,$3,$4}'
4 aa bb cc dd? ? ? ?# 共四個字符,且每個字段的內容,-F 中支持正則表達式
實際使用時應測試好它所支持的正則表達式的語法,以前好像還嘗試過 awk 的正則表達式的切割功能,還以為需要用 Python 的實現類似的操作。
曾經想過用 Python 的切分字符串的方式 (cut.py)
#!/usr/bin/env python
import sys
from optparse import OptionParser
import re
parser = OptionParser()
parser.add_option('-d', '--delimiter', default='\t')
parser.add_option('-f', '--fields')
(options, args) = parser.parse_args()
indexes = [(int(i) - 1) for i in options.fields.split(',')]
regex = re.compile(options.delimiter)
for line in sys.stdin:
fields = regex.split(line.rstrip())
out = ' '.join([fields[i] for i in indexes])
print(out)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#!/usr/bin/env python
importsys
fromoptparseimportOptionParser
importre
parser=OptionParser()
parser.add_option('-d','--delimiter',default='\t')
parser.add_option('-f','--fields')
(options,args)=parser.parse_args()
indexes=[(int(i)-1)foriinoptions.fields.split(',')]
regex=re.compile(options.delimiter)
forlineinsys.stdin:
fields=regex.split(line.rstrip())
out=' '.join([fields[i]foriinindexes])
print(out)
然后執行
$ echo "aa,bb,,cc:dd" | cut.py -d",+|:" -f1,2,4? ? # Python 的正則表達式也需多測試
aa bb dd
輸出匹配后的下一行
通常我們的需求是用? grep 查找到并輸出匹配行,有時我們想輸出匹配行的下一行,或下幾行,比如說對 ini?文件
[memory]
max=8G
[bandwidth]
max=4G
我們想要找到含有 [memory] 的下一行的 max 值而不是別處的 max
可以用? awk?命令
cat test.ini | awk '/\[memory\]/{getline;print}'? ?#\[ 為轉義 [?符號
max=8G
或者用 sed 命令(sed 是什么?Stream EDitor, 流編程器,也可說是像 awk 一樣另成一種編程語言
cat test.ini | sed -n '/[memory]/{n;p;}'? ?# 很像 awk 的? getline;print
max=8G
sed 中的命令非常精簡,都用單字母,如 a: append, s: substitue, n: next, p: print。如果要用來處理字符串替換的操作 sed 就是最好的編程工具。
grep?本身也能完成類似的功能
$ cat test.ini | grep -A1 '\[memory\]'? ? # 往下多顯示一行? -A, --after-context=NUM 從當前往下多少行,往前是 -B
[memory]
max=8G
前面說過 awk? 本身就是個編程語言的,所以還能加入更多代碼
$ cat test.ini | awk '/\[memory\]/{for(i=0;i<4;i++)getline;print $0}'
max=4G
//或者
$ cat test.ini | awk -v lines=4 '/\[memory\]/{for(i=lines;i;--i) getline; print $0}'
max=4G
awk 和 sed 是可以直接讀取文件的,所以前面的命令可以不用 cat test.ini 到它的管道操作,而可以
$ awk '/\[memory\]/{for(i=0;i<4;i++)getline;print $0}' test.ini
$ sed -n '/[memory]/{n;p;}' test.ini
sort?命令按某列排序
sort 命令可以幫我們對文本行排序,默認以整行字符串為比較單位,主要參數有
-n:? --numberic-sort, 比較數字大小而非字符串來排序
-r:--reverse, 逆序排列
-f: --ignore-case, 忽略大小寫排序
這兒我們了解另一種排序需求,即按文件中某一列進行排序,如果有如下文件 planets.txt, 內容為
Moon,3
Sun,1
Earth,2
1
2
3
Moon,3
Sun,1
Earth,2
我們想要按第二列進行序列后輸出全部內容,那么命令為
$ sort -t, -k2 planets.txt
Sun,1
Earth,2
Moon,3
解析:
-t: --field-separator, 以逗號為分割符, 默認是以空格分割
-k2: --key, 先取第二列為排序依據
除此之外,sort 還有以下兩個有意思的功能
-R: --random-sort, 隨機打亂順序
-u: --unique, 去重功能,從此告別 sort | uniq 這樣的管道操作
看一下 -u 去重的功能,修改 planets.txt?內容如下
Moon,3
Sun,1
Earth,2
XXX,1
1
2
3
4
Moon,3
Sun,1
Earth,2
XXX,1
$ sort -t, -k2 -u planets.txt
Sun,1
Earth,2
Moon,3
在用 -t, -k2 時還是按照重復列來去重的。
批處理利器 xargs?命令
提起 xargs 命令時讓人不禁想起 find 這一絕配,通常是 find 找到某些符合條件的文件后用管道傳遞給? xargs? 去批量操作,有時也會 find -exec 命令來操作。比如
$ find . -type f -size +800M -exec rm {} \;? ? ? ? ? ? ? ? ? ? ? ? ?//或
$ find . -type f -size +800M -exec rm {} +
除此之外也會用到 xargs 命令與 find?配合
$ find . | xargs -0 rm -f
$ find . -type f | xargs -I {} cp {} /var/www
上面第一個命令,找到的內容是放到 rm -f 后面,可以不用 {} 的形式; ?如果不加 -0 (數字零)參數,rm 刪除太多文件時會出現 Argument list too long 的錯誤。第二個命令因為內容放在 cp 命令中間,所以要用 {} 點位符; 同樣的,如果操作的文件太多,在 xargs? 命令中也要加上? -0 參數。
除此之外,xargs? 還能把單行轉成多行
$ cat <
> a b c d
> e f
> g
> EOF
a b c d e f g
更多功能見文后的鏈接。
鏈接:
總結
以上是生活随笔為你收集整理的linux开发常用脚本,记录自己常用的一些 Linux Shell 脚本的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: u盘无法释读怎么办 U盘读不出怎么办
- 下一篇: 哪些因素不会限制linux服务器并发,嵌