LinuxSir.cn,穿越时空的Linuxsir!

 找回密码
 注册
搜索
热搜: shell linux mysql
查看: 1213|回复: 1

awk & sed 小小记录

[复制链接]
发表于 2005-12-1 23:38:09 | 显示全部楼层 |阅读模式
sed 是基于行的,按顺序对每一行执行命令,然后将结果写入标准输出


sed -e 'd' /etc/services
打开文件后将每一行读入缓冲区执行编辑命令("删除行"),然后输出缓冲区,然后对每一行做这些重复步骤.

即将指定的编辑文件缓冲后删除

sed -e '1d' /etc/services | more
从输出流中除去第一行

sed -e '1,10d' /etc/services | more
当用逗号将两个地址分开时,将后面的命令运用到第一个地址开始,到第二个地址结束的范围.

sed -e '/^#/d' /etc/services | more
'/^#/d'
规则表达式地址总是由斜杠括起,
/./将与包含至少一个字符的任何行匹配
/../将与包含至少两个字符的任何行匹配
/^#/将以'#'开始的任何行匹配
/^$/将与所有空行匹配
/}^/将与所有以'}'(无空格)结束的任何行匹配
/}*^/将与'}'后面跟有零或多个空格结束的任何行匹配
/[abc]/将与包含小写'a','b','c'的任何行匹配
/^[abc]/将与以'a','b',或'c'开始的任何行匹配
sed -e '/regexp/d' /path/to/my/test/file | more
删除任何匹配的行


sed -n -e '/regexp/p' /path/to/my/test/file | more
'-n' 选项告诉sed除非明确要求打印模式空间,否则不这样做
'-p'替换了'-d'这样就明确要求sed打印模式空间,
只打印匹配部份的行

cat test
abc
def
hij
BEGIN
a
b
c
d
e
f
g
END
abc
hij


sed -n -e '/BEGIN/,/END/p' /my/test/file | more
BEGIN
a
b
c
d
e
f
g
END
如果没有发现'BEGIN',那么将不打印数据.
如果有发现'BEGIN'无'END'那么将打印后续行,因为面向流的特性,不知道是否会出现"END"



sed -n -e '/main[[:space:]]*(/,/^}/p' test | more
输出C源文件中main()函数
/main[[:space:]]*
'[[:space:]]'是一个特殊的关键字,它告诉sed与Tab或空格匹配,
'/^}'将与任何出现在新行行首的}字符匹配

[:alnum:] 字母数字 [a-z A-Z 0-9]
[:alpha:] 字母 [a-z A-Z]
[:blank:] 空格或制表键
[:graph:] 任何可视字符(无空格)
[:space:] 空格
[:cntrl:] 任何控制字符
[:print:] 非控制字符
[:digit:] 数字 [0-9]
[:lower:] 小写 [a-z]
[:upper:] 大写 [A-Z]
[:punct:] 标点字符
[:xdigit:] 十六进制数字 [0-9 a-f A-F]

sed -e 's/foo/bar/' myfile.txt
sed -e '1,10s/enchantment/entrapment/g' myfile2.txt


sed -e 's:/usr/local:/usr:g' mylist.txt
如果需要在规则表达式中指定分隔符,可以在前面加入反斜杠.


awk
很棒的语言

awk '{print}' /etc/passwd
指定passwd文件为输入文件,依次对passwd每一行执行print命令
花括号用于将几块代码组合到一起

所有的输出都发送到stdout,所以其结果与cat passwd完全相同.


awk '{ print $0 }' /etc/passwd
$0变量表示整个当前行,所以print与print $0作用完全一样

awk '{ print "" }' /etc/passwd
对于passwd文件中的每一行,awk都输出一个空白行.

awk '{ print "peter"}' /etc/passwd
对于passwd文件中的每一行,awk都输出一个peter.

awk -F":" '{print $1} /etc/passwd
在调用awk时,用-F选项指定":"作为字段分隔符.
awk 处理print $1时,会打印出输入文件中每一行出现的每一个字段.

awk -F":" '{print $1$3} /etc/passwd
打印passwd文件的第一,三个字段,正好是用户名和用户标识字段

awk -F":" ' {print $1 " " $3}' /etc/passwd
这样就可以在显示中有" "空格了。

awk -F":" '{print "username:"$1 " uid:"$3}' /etc/passwd
可以在顯示前插入一些文件標簽

cat myscript.awk
BEGIN {
        FS=":"
}
{
        print $1 }
awk -f myscript.awk /etc/passwd


在腳本中通過設置FS變數,而在命令行上向awk  傳遞-F":"?碓O置FS

BEGIN和END塊
對於每個輸入行,awk會執行每個腳本代碼一次。
然而在awk處理輸入文件中的文本之前執行初始化代碼。
awk允許定義一個BEGIN塊,故在處理文件前會執行BEGIN,
因此它是初始化FS(欄位分隔符)變數,
列印頁眉或初始化其它在程式中以後會引用的全局變數的極佳位置.

awk還提供了另一個特殊塊,叫END塊。
在處理了輸入文件中的所有行之後執行這個塊。


#awk '{print}'  tmp
ok
no
yes
hi
0.5
9
hello
3
55.6
good
not
ok


#awk '/ok/{print}' tmp
ok
ok

#awk '/[0-9].[0-9]*/{print}' tmp
0.5
55.6


# awk -F":" '$1=="sp02001" {print $5}' /etc/passwd
mis

有比較完整的運算符包括"==","<"">","<=",">="和"!=","~","!~",“||”,“&&"
加/減/乘/除賦值運算符

"~"表示“匹配”或者叫包括吧
"!~"表示“不匹配”
awk -F":" '$1!~/peter/{print}' /etc/passwd | less
顯示裏的第一列不會有peter出現

#awk -F":" '$1~/peter/{print}' /etc/passwd
peter:x:500:100::/home/peter:/bin/bash
peter$:x:10085:421:machine name -sp02001:/dev/null:/bin/false



[root@shlinux tmp]# awk '{print}' awkscript.awk
BEGIN {
        FS=":"
}
{
        if ($1 ~/peter/){
                print }}
[root@shlinux tmp]# awk -f awkscript.awk /etc/passwd
peter:x:500:100::/home/peter:/bin/bash
peter$:x:10085:421:machine name -sp02001:/dev/null:/bin/false
顯示第一欄位是peter的。


[root@shlinux tmp]# awk '{print}' ms1.awk
BEGIN{
        FS=":"
}
{
        if ($1 == "a"){
                if ($2=="b"){           print "ab"              }
                else {                  print "astart" }
                        }
        else if($3=="bar"){             print "twoa"}
                else {  print "bar" }
}
[root@shlinux tmp]# awk -f ms1.awk dd
bar
ab
[root@shlinux tmp]# cat dd
aa:b:aaabar
a:b:eee


# awk -F":" '$1=="peter"&&$2=="x"{print}' /etc/passwd
peter:x:500:100::/home/peter:/bin/bash



[root@shlinux tmp]# cat awk1
BEGIN { x=0 }
/^$/{ x=x+1 }
END{print "I found "x" blank lines. "}

#awk -f awk1 s
I found 3 blank lines.
[root@shlinux tmp]# awk '{print}' s

a

b
c
d

e
awk變數都是在內部按字元串形式存儲的。
只要變數包含有效數位字元串,awk會自動處理字元串到數位的轉換
所以awk變數是簡單的


# awk '{print}' awk2
BEGIN {
x="1.01"
x=x+1
print x
}
# awk -f awk2
2.01



# awk '{print($1^2+1)}' num
1
2
5
10
17
26
[root@shlinux tmp]# awk '{print}' num
0
1
2
3
4
5

"+"規則表達式字符,表示“一個或多個前一字元”
如果欄位由空格分隔(一個或多個空格或tab),可能想要將FS設置成如下表達式:
FS="[[:space:]+"
當然這?K非必要,因為缺省的情況下,FS設置成單一空格字元
awk解釋成“一個或多個空格或tab"
如果由單啟“foo"分隔,後面跟著三個數位,以上規則表:
FS="foo[0-9][0-9][0-9]


NF為欄位數量,awk會自動將該變數設置成當前記錄中的欄位數量。
NR為當前記錄編號,awk將第一個記錄算作記錄號1
這兩個變數通常不需要賦值的。

awk '{print}' awk5
(NR<5)||(NR>280)
[root@shlinux tmp]# awk -f awk5 /etc/passwd | more
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/bin/sh
daemon:x:2:2:daemon:/sbin:/bin/sh
adm:x:3:4:adm:/var/adm:/bin/sh
ss0213:x:65643:9000::/home/ss0213:/bin/false
a0612:x:65644:10048::/home/a0612:/bin/false
sl02020:x:65645:6500::/home/samba/sl02020:/bin/false
a0581:x:65646:10048::/home/a0581:/bin/false
显示前五行和行号>280的

a0581:x:65646:10048::/home/a0581:/bin/bash  7
[root@shlinux tmp]# awk -F":" '{print $0 "  " NF}' /etc/passwd
NF結果為7
发表于 2005-12-3 08:36:07 | 显示全部楼层
记得用上
  1. 内容
复制代码
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 返回顶部 返回列表