sed与awk总结

>  # 每行后面增加一行空行 
>  awk '1;{print ""}' 
>  awk 'BEGIN{ORS="\n\n"};1' 


>  # 每行后面增加一行空行。输出文件不会包含连续的两个或两个以上的空行 
>  # 注意:在Unix系统, DOS行包括的 CRLF (\r\n) 通常会被作为非空行对待 
>  # 因此 'NF' 将会返回TRUE。 
>  awk 'NF{print $0 "\n"}' 


>  # 每行后面增加两行空行 
>  awk '1;{print "\n"}' 


> 编号和计算: 


>  # 以文件为单位,在每句行前加上编号 (左对齐). 
>  # 使用制表符 (\t) 来代替空格可以有效保护页变的空白。 
>  awk '{print FNR "\t" $0}' files* 


>  # 用制表符 (\t) 给所有文件加上连贯的编号。 
>  awk '{print NR "\t" $0}' files* 


>  # number each line of a file (number on left, right-aligned) 
>  # Double the percent signs if typing from the DOS command prompt. 
>  awk '{printf("%5d : %s\n", NR,$0)}' 


>  # 给非空白行的行加上编号 
>  # 记得Unix对于 \r 的处理的特殊之处。(上面已经提到) 
>  awk 'NF{$0=++a " :" $0};{print}' 
>  awk '{print (NF? ++a " :" :"") $0}' 


>  # 计算行数 (模拟 "wc -l") 
>  awk 'END{print NR}' 


>  # 计算每行每个区域(行)之和 
>  awk '{s=0; for (i=1; i<=NF; i++) s=s+$i; print s}' 


>  # 计算所有行所有区域的总和 
>  awk '{for (i=1; i<=NF; i++) s=s+$i}; END{print s}' 


>  # 打印每行每区域的绝对值 
>  awk '{for (i=1; i<=NF; i++) if ($i < 0) $i = -$i; print }' 
>  awk '{for (i=1; i<=NF; i++) $i = ($i < 0) ? -$i : $i; print }' 


>  # 计算所有行所有区域(词)的个数 
>  awk '{ total = total + NF }; END {print total}' file 


>  # 打印包含 "Beth" 的行数 
>  awk '/Beth/{n++}; END {print n+0}' file 


>  # 打印第一列最大的行 
>  # 并且在行前打印出这个最大的数 
>  awk '$1 > max {max=$1; maxline=$0}; END{ print max, maxline}' 


>  # 打印每行的列数,并在后面跟上此行内容 
>  awk '{ print NF ":" $0 } ' 


>  # 打印每行的最后一列 
>  awk '{ print $NF }' 


>  # 打印最后一行的最后一列 
>  awk '{ field = $NF }; END{ print field }' 


>  # 打印列数超过4的行 
>  awk 'NF > 4' 


>  # 打印最后一列大于4的行 
>  awk '$NF > 4' 


> 文本转换和替代: 


>  # 在Unix环境:转换DOS新行 (CR/LF) 为Unix格式 
>  awk '{sub(/\r$/,"");print}' # 假设每行都以Ctrl-M结尾 


>  # 在Unix环境:转换Unix新行 (LF) 为DOS格式 
>  awk '{sub(/$/,"\r");print} 


>  # 在DOS环境:转换Unix新行 (LF) 为DOS格式 
>  awk 1 


>  # 在DOS环境:转换DOS新行 (CR/LF) 为Unix格式 
>  # DOS版本的awk不能运行, 只能用gawk: 
>  gawk -v BINMODE="w" '1' infile >outfile 


>  # 用 "tr" 替代的方法。 
>  tr -d \r <infile >outfile # GNU tr 版本为 1.22 或者更高 


>  # 删除每行前的空白(包括空格符和制表符) 
>  # 使所有文本左对齐 
>  awk '{sub(/^[ \t]+/, ""); print}' 


>  # 删除每行结尾的空白(包括空格符和制表符) 
>  awk '{sub(/[ \t]+$/, "");print}' 


>  # 删除每行开头和结尾的所有空白(包括空格符和制表符) 
>  awk '{gsub(/^[ \t]+|[ \t]+$/,"");print}' 
>  awk '{$1=$1;print}' # 每列之间的空白也被删除 


>  # 在每一行开头处插入5个空格 (做整页的左位移) 
>  awk '{sub(/^/, " ");print}' 


>  # 用79个字符为宽度,将全部文本右对齐 
>  awk '{printf "%79s\n", $0}' file* 


>  # 用79个字符为宽度,将全部文本居中对齐 
>  awk '{l=length();s=int((79-l)/2); printf "%"(s+l)"s\n",$0}' file* 


>  # 每行用 "bar" 查找替换 "foo" 
>  awk '{sub(/foo/,"bar");print}' # 仅仅替换第一个找到的"foo" 
>  gawk '{$0=gensub(/foo/,"bar",4);print}' # 仅仅替换第四个找到的"foo" 
>  awk '{gsub(/foo/,"bar");print}' # 全部替换 


>  # 在包含 "baz" 的行里,将 "foo" 替换为 "bar" 
>  awk '/baz/{gsub(/foo/, "bar")};{print}' 


>  # 在不包含 "baz" 的行里,将 "foo" 替换为 "bar" 
>  awk '!/baz/{gsub(/foo/, "bar")};{print}' 


>  # 将 "scarlet" 或者 "ruby" 或者 "puce" 替换为 "red" 
>  awk '{gsub(/scarlet|ruby|puce/, "red"); print}' 


>  # 倒排文本 (模拟 "tac") 
>  awk '{a[i++]=$0} END {for (j=i-1; j>=0;) print a[j--] }' file* 


>  # 如果一行结尾为反斜线符,将下一行接到这行后面 
>  # (如果有连续多行后面带反斜线符,将会失败) 
>  awk '/\\$/ {sub(/\\$/,""); getline t; print $0 t; next}; 1' file* 


>  # 排序并打印所有登录用户的姓名 
>  awk -F ":" '{ print $1 | "sort" }' /etc/passwd 


>  # 以相反的顺序打印出每行的前两列 
>  awk '{print $2, $1}' file 


>  # 调换前两列的位置 
>  awk '{temp = $1; $1 = $2; $2 = temp}' file 


>  # 打印每行,并删除第二列 
>  awk '{ $2 = ""; print }' 


>  # 倒置每行并打印 
>  awk '{for (i=NF; i>0; i--) printf("%s ",i);printf ("\n")}' file 


>  # 删除重复连续的行 (模拟 "uniq") 
>  awk 'a !~ $0; {a=$0}' 


>  # 删除重复的、非连续的行 
>  awk '! a[$0]++' # 最简练 
>  awk '!($0 in a) {a[$0];print}' # 最有效 


>  # 用逗号链接每5行 
>  awk 'ORS=%NR%5?",":"\n"' file #bug awk 'ORS=NR%5?",":"\n"' file 


> 选择性的打印某些行: 


>  # 打印文件的前十行 (模拟 "head") 
>  awk 'NR < 11' 


>  # 打印文件的第一行 (模拟 "head -1") 
>  awk 'NR>1{exit};1' 


>  # 打印文件的最后两行 (模拟 "tail -2") 
>  awk '{y=x "\n" $0; x=$0};END{print y}' 


>  # 打印文件的最后一行 (模拟 "tail -1") 
>  awk 'END{print}' 


>  # 打印匹配正则表达式的行 (模拟 "grep") 
>  awk '/regex/' 


>  # 打印不匹配正则表达式的行 (模拟 "grep -v") 
>  awk '!/regex/' 


>  # 打印匹配正则表达式的前一行,但是不打印当前行 
>  awk '/regex/{print x};{x=$0}' 
>  awk '/regex/{print (x=="" ? "match on line 1" : x)};{x=$0}' 


>  # 打印匹配正则表达式的后一行,但是不打印当前行 
>  awk '/regex/{getline;print}' 


>  # 以任何顺序查找包含 AAA、BBB 和 CCC 的行 
>  awk '/AAA/; /BBB/; /CCC/' 


>  # 以指定顺序查找包含 AAA、BBB 和 CCC 的行 
>  awk '/AAA.*BBB.*CCC/' 


>  # 打印长度大于64个字节的行 
>  awk 'length > 64' 


>  # 打印长度小于64个字节的行 
>  awk 'length < 64' 


>  # 打印从匹配正则起到文件末尾的内容 
>  awk '/regex/,0' 
>  awk '/regex/,EOF' 


>  # 打印指定行之间的内容 (8-12行, 包括第8和第12行) 
>  awk 'NR==8,NR==12' 


>  # 打印第52行 
>  awk 'NR==52' 
>  awk 'NR==52 {print;exit}' # 对于大文件更有效率 


>  # 打印两个正则匹配间的内容 (包括正则的内容) 
>  awk '/Iowa/,/Montana/' # 大小写敏感 


> 选择性的删除某些行: 


>  # 删除所有空白行 (类似于 "grep '.' ") 
>  awk NF 
>  awk '/./' 

awk不显示最后一列

awk 'NF--' file 
此命令遇到空行会报错,所以使用:

awk 'NF{NF--}1' file等同于awk 'NF{NF=NF-1}1'  file

1或任意数字类似print$0

awk '{$NF=null;print $0}' file
null是指将最后一列置空,也可以将其它列置空,如awk '{$1=null;print $0}' file

awk '$NF=" "' file

sed '/^\s*$/d' test | awk 'NF--'
先去掉空行再去掉最后一列

列求和
awk 'BEGIN{total=0}{total+=$1}END{print total}'

awk 'pattern{action}' file
一般awk的格式是这样的。

如果写成awk 'pattern' file,那么action默认为{print $0};
pattern如果是个定值,则判断该值是否为00为false,非0为true);
pattern如果是个计算表达式,则判断计算结果是否为0;
pattern如果是个awk 命令,则判断其返回值是否为0。

这样就能理解awk '1' file的意义了:
在这里action为空,因此默认为{print $0}1为定值,非0,因此执行action,即print $0。



awk '!a[$1]++' file 

打印每行第一列重复的行中的第一行


去掉重复的行
awk '!a[$0]++' file


按列分类求和
awk '{a[$1]+=$2}END{for(i in a)print i,a[i]}' file

--------------------------------------------------------------------------------------
1.取行的最后几个字符
echo "SYBASE4"|sed 's/.*\(....\)$/\1/'

2.取行的前几个字符
echo "SYBASE4"|sed 's/^\(........\).*/\1/'

3.删除文件中的空行
sed '/^$/d' filename

4.替换文件中的空行为0
sed 's/^$/0/g' -i filename


5、将两行合并成一行:
sed 'N;s/\n/ /g' 


6、将一个文件中的内容将另一个文件中的每行内容通过变量进行替换
#!/bin/sh
for sheng in `cat shenglist`
do
  sed -i "s/$sheng.*/$sheng/g" liuliangfenbu.txt
done

按位相加
sed -r 's/[0-9]/&+/g' urfile|sed -r 's/[\+][^\+]*$//'
awk  'BEGIN{FS=""}{for (i=1;i<=NF;i++) sum+=$i;print sum}' urfile
echo 65734843|awk  'BEGIN{FS="";OFS="+"}{$1=$1;print $0}'|bc




打印4001行至行尾:
sed -n '4001,$p' del_domainlist


在shell中遇到字符串问题,首先考虑的是grep ,sed ,awk , cut

不先讲这几个命令了,先来看一下字符串截取中用简单方法就能做到的事情 ${}1)shell中的单引号比双引号的区别:单引号关闭所有有特殊作用的字符,而双引号只要求shell忽略大多数,具体的说,就是①美元符号②反引号③反斜杠,这3种特殊字符不被忽略
(2)求字符串长度  ----- (1)expr $x:.*(2)${#x}3)求字符串子串  ----- ${x:$pos:$len},其中$pos位置,$len长度,其中$len可省略

(4)字符串替换    ----- ${x/a/b} 用b替换a ; ${x//a/b}用b替换所有的a

(5)字符串首尾截取----- ${x##*/}去掉所有/左边的字符,也可用其它匹配代替*/  ${x#*/}只去掉第一次出现/左边所有的字符。顺序为从左到右.${x%%/*}去掉所有/右边的字符,${x%/*}去掉第一次出现/右边的字符,顺序为从右到左.

eg,
#!/bin/bash
y=kdjfkd:dfkdjfkd:8888:9899899:kdjfkdfj
q=`echo $y | cut -d":" -f4` //以:截取,取第四个字段即9899899
m=${q##*8} //去掉所有8左边的字符
echo $m
n=${q#*8} //去掉第一个8左边的字符
echo $n
result:99
          998996)Shell数组定义 a=(1 2 3 4),不能有空格,比如a =(1 2 3 4)和a=(1 2 3 4)都是不允许的。



(7)数组长度: ${#a[@]}或者 ${#a[*]} ;全部数组 ${a[@]}或{$a[*]}返回1 2 3 48)数组元素的长度   ${#a[i]},i为下标,和其它语言一样,从0开始,数组元素${a[i]}9)awk默认使用空格作为域分隔符,

"+""?"只适用awk而不适用sed和grep

awk条件操作符:<,<=,>=,==,!=,~,!~

awk字符串处理函数:gsub(r,s),gsub(r,s,t),index(s,t)等

awk自定义环境变量:FILENAME,FNR,FS,NF,NR等

awk -F : '{print $1}' /etc/passwd 打印第一列的值, $0 打印全部的值

awk -F : 'BEGIN {print "name       passwd\n-----------------"} {print $1"\t"$5}'END {print "End of file"}' /etc/passwd 输出增加头尾

awk '{if($0~/root/) print $0}' /etc/passwd输出匹配"root"的行,等价于awk '$0~/root/' /etc/passwd




(10)无论命令是什么?sed并不与初始化文件打交道,它操作的只是文件的一个拷贝。如果不重定向到一个文件,直接在标准输出(显示屏)显示。

搜索替换是sed的拿手好戏。

sed -n '1,$p' /etc/passwd 打印从1到最后一行的所有内容

sed -e '/root/=' /etc/passwd打印出现"root"的行号和所有行

sed -n '/root/=' /etc/passwd只打印行号

sed -n -e '/root/p'  /etc/passwd  只打印出现"root"的匹配行

sed -n -e '/root/p' -e '/root/=' /etc/passwd 打印匹配行和行号

sed 's/^M//g' /etc/passwd 删除行尾控制字符(^M)= ctrl+v+m

sed 's/^0*//g' /etc/passwd 删除行首的多个零

(11)grep 一般用来搜索字段或字串,sed用来搜索或者替换,awk可以进行复杂的运算和定制操作





(12)先不要管Shell的版本,来看看Shell 变量,在Shell中有三种变量:系统变量,环境变量,用户变量

系统变量:

$# 传递到脚本的参数个数;

$$脚本运行的当前进程id;

$?最后命令的退出状态,0表成功;

$!上一个命令的PID ;

$@ 以"参数1" "参数2" ... 形式保存所有参数 ;

$*"参数1 参数2 ... " 形式保存所有参数 ;$0表示脚本名称

用户变量:用set命令查看

环境变量:用setenv查看




(13)不同的shell版本有不同数组赋值方法,而bourne shell (如bash)中不支持数组方式。



(14)查看目录或者文件,符号链接:ls -l | grep '^d' 或者 ls -l | grep '^-',ls -l | grep '^l'15)查看最后一列的指:ls -l | grep '^l' | awk '{print $NF}' (默认以空格分隔),在awk中,NF表示字段数,$NF表示最后一个字段


你可能感兴趣的:(Linux,shell,awk)