本文将介绍Linux下使用Shell处理文本时最常用的工具:
find、grep、xargs、sort、uniq、tr、cut、paste、wc、sed、awk;
提供的例子和参数都是最常用和最为实用的;
我对shell脚本使用的原则是命令单行书写,尽量不要超过2行;
如果有更为复杂的任务需求,还是考虑python吧;
1
|
find . ( -name "*.txt" -o -name "*.pdf" ) -print |
1
|
find . -regex ".*(.txt|.pdf)$" |
-iregex: 忽略大小写的正则
1
|
find . ! -name "*.txt" -print |
1
|
find . -maxdepth 1 - type f |
1
|
find . - type d -print // 只列出所有目录 |
-type f 文件 / l 符号链接
1
|
find . -atime 7 - type f -print |
1
|
find . - type f -size +2k |
按权限查找:
1
|
find . - type f -perm 644 -print // 找具有可执行权限的所有文件 |
按用户查找:
1
|
find . - type f -user weber -print // 找用户weber所拥有的文件 |
1
|
find . - type f -name "*.swp" -delete |
1
|
find . - type f -user root - exec chown weber {} ; // 将当前目录下的所有权变更为weber |
注:{}是一个特殊的字符串,对于每一个匹配的文件,{}会被替换成相应的文件名;
eg:将找到的文件全都copy到另一个目录:
1
|
find . - type f -mtime +10 -name "*.txt" - exec cp {} OLD ; |
1
|
- exec . /commands .sh {} \; |
默认使用’n‘作为文件的定界符;
-print0 使用”作为文件的定界符,这样就可以搜索包含空格的文件;
grep match_patten file // 默认访问匹配行
1
|
grep -c "text" filename |
-n 打印匹配的行号
-i 搜索时忽略大小写
-l 只打印文件名
1
|
grep "class" . -R -n |
1
|
grep -e "class" -e "vitural" file |
1
|
grep "test" file * -lZ| xargs -0 rm |
xargs 能够将输入数据转化为特定命令的命令行参数;这样,可以配合很多命令来组合使用。比如grep,比如find;
-d 定义定界符 (默认为空格 多行的定界符为 n)
-n 指定输出为多行
-I {} 指定替换字符串,这个字符串在xargs扩展时会被替换掉,用于待执行的命令需要多个参数时
eg:
1
|
cat file .txt | xargs -I {} . /command .sh -p {} -1 |
-0:指定为输入定界符
eg:统计程序行数
1
|
find source_dir/ - type f -name "*.cpp" -print0 | xargs -0 wc -l |
字段说明:
-n 按数字进行排序 VS -d 按字典序进行排序
-r 逆序排序
-k N 指定按第N列排序
eg:
1
2
|
sort -nrk 1 data.txt sort -bd data // 忽略像空格之类的前导空白字符 |
1
|
sort unsort.txt | uniq |
1
|
sort unsort.txt | uniq -c |
1
|
sort unsort.txt | uniq -d |
可指定每行中需要比较的重复内容:-s 开始位置 -w 比较字符数
1
2
|
echo 12345 | tr ‘0-9‘ ‘9876543210‘ // 加解密转换,替换对应字符 cat text| tr ‘t‘ ‘ ‘ // 制表符转空格 |
1
|
cat file | tr -d ‘0-9‘ // 删除所有数字 |
-c 求补集
1
2
|
cat file | tr -c ‘0-9‘ // 获取文件中所有数字 cat file | tr -d -c ‘0-9 n‘ // 删除非数字数据 |
1
|
cat file | tr -s ‘ ‘ |
1
|
eg: tr ‘[:lower:]‘ ‘[:upper:]‘ |
1
|
cut -f2,4 filename |
1
|
cut -f3 --complement filename |
1
|
cat -f2 -d ";" filename |
1
2
|
cut -c1-5 file // 打印第一到5个字符 cut -c-2 file // 打印前2个字符 |
将两个文本按列拼接到一起;
1
2
3
4
5
6
7
8
9
10
11
|
cat file1 1 2 cat file2 colin book paste file1 file2 1 colin 2 book |
默认的定界符是制表符,可以用-d指明定界符
paste file1 file2 -d “,”
1,colin
2,book
wc -l file // 统计行数
wc -w file // 统计单词数
wc -c file // 统计字符数
1
|
seg ‘s/text/replace_text/‘ file // 替换每一行的第一处匹配的text |
1
|
seg ‘s/text/replace_text/g‘ file |
默认替换后,输出替换后的内容,如果需要直接替换原文件,使用-i:
1
|
seg -i ‘s/text/repalce_text/g‘ file |
1
|
sed ‘/^$/d‘ file |
1
2
|
echo this is en example | seg ‘s/\w+/[&]/g‘ $>[this] [is] [en] [example] |
1
|
sed ‘s/hello([0-9])/1/‘ |
1
|
sed ‘s/$var/HLLOE/‘ |
当使用双引号时,我们可以在sed样式和替换字符串中指定变量;
1
2
3
4
5
|
eg: p=patten r=replaced echo "line con a patten" | sed "s/$p/$r/g" $>line con a replaced |
1
|
sed ‘s/^.{3}/ |
1
|
echo -e "line1nline2" | awk ‘BEGIN{print "start"} {print } END{ print "End" }‘ |
1
2
3
|
echo | awk ‘ {var1 = "v1" ; var2 = "V2" ; var3= "v3" ; print var1, var2 , var3; }‘ $>v1 V2 v3 |
1
2
3
|
echo | awk ‘ {var1 = "v1" ; var2 = "V2" ; var3= "v3" ; print var1 "-" var2 "-" var3; }‘ $>v1-V2-v3 |
NR:表示记录数量,在执行过程中对应当前行号;
NF:表示字段数量,在执行过程总对应当前行的字段数;
$0:这个变量包含执行过程中当前行的文本内容;
$1:第一个字段的文本内容;
$2:第二个字段的文本内容;
1
|
echo -e "line1 f2 f3n line2 n line 3" | awk ‘{print NR":"$0"-"$1"-"$2}‘ |
1
|
awk ‘{print $2, $3}‘ file |
1
|
awk ‘ END {print NR}‘ file |
1
2
|
echo -e "1n 2n 3n 4n" | awk ‘BEGIN{num = 0 ; print "begin" ;} { sum += $1;} END {print "==" ; print sum }‘ |
1
2
3
|
var=1000 echo | awk ‘{print vara}‘ vara=$var # 输入来自stdin awk ‘{print vara}‘ vara=$var file # 输入来自文件 |
awk ‘NR awk ‘NR==1,NR==4 {print}’ file #行号等于1和4的打印出来
awk ‘/linux/’ #包含linux文本的行(可以用正则表达式来指定,超级强大)
awk ‘!/linux/’ #不包含linux文本的行
使用-F来设置定界符(默认为空格)
awk -F: ‘{print $NF}’ /etc/passwd
使用getline,将外部shell命令的输出读入到变量cmdout中;
1
|
echo | awk ‘{"grep root /etc/passwd" | getline cmdout; print cmdout }‘ |
for(i=0;ifor(i in array){print array[i];}
eg:
以逆序的形式打印行:(tac命令的实现)
1
2
3
4
|
seq 9| awk ‘{lifo[NR] = $0; lno=NR} END{ for (;lno>-1;lno--){print lifo[lno];} } ‘ |
1
|
awk ‘NR<=10{print}‘ filename |
1
2
|
awk ‘{buffer[NR%10] = $0;} END{ for (i=0;i<11;i++){ \ print buffer[i %10]} } ‘ filename |
1
|
ls -lrt | awk ‘{print $6}‘ |
1
|
ls -lrt | cut -f6 |
1
|
seq 100| awk ‘NR==4,NR==6{print}‘ |
1
|
awk ‘/start_pattern/, /end_pattern/‘ filename |
eg:
1
2
|
seq 100 | awk ‘/13/,/15/‘ cat /etc/passwd | awk ‘/mai.*mail/,/news.*news/‘ |
index(string,search_string):返回search_string在string中出现的位置
sub(regex,replacement_str,string):将正则匹配到的第一处内容替换为replacement_str;
match(regex,string):检查正则表达式是否能够匹配字符串;
length(string):返回字符串长度
1
|
echo | awk ‘{"grep root /etc/passwd" | getline cmdout; print length(cmdout) }‘ |
printf 类似c语言中的printf,对输出进行格式化
eg:
1
|
seq 10 | awk ‘{printf "->%4sn", $1}‘ |
1
2
3
4
5
6
|
while read line; do echo $line; done < file .txt 改成子shell: cat file .txt | ( while read line; do echo $line; done ) |
1
2
3
4
|
for word in $line; do echo $word; done |
${string:start_pos:num_of_chars}:从字符串中提取一个字符;(bash文本切片)
${#word}:返回变量word的长度
1
2
3
4
|
for ((i=0;i<${ #word};i++)) do echo ${word:i:1); done |
原文:http://www.cnblogs.com/SZLLQ2000/p/5327956.html