您的位置:首页 > 运维架构 > Shell

《Linux Shell Scripting Cookbook》Linux常用命令笔记(三)

2013-11-24 17:39 621 查看

一 cut

1、cut -f FIELD_LIST filename ,cut 用来根据列切割,每列又称为域(field),不同域之间用逗号分隔。

$ cut -f 2,3 filename          # 取filename中每行的第2和第3列输出到stdout中。

2、Tab 键被用来作为默认分隔符,默认会打印不含分隔符的行,可以使用 -s 选项不输出。

可以使用 -d 选项来指定分隔符,如:

$ cat delimited_data.txt
No;Name;Mark;Percent
1;Sarath;45;90
2;Alex;49;98
3;Anu;45;90
$ cut -f2 -d";" delimited_data.txt
Name
Sarath
Alex
Anu

另外,需注意 cut 是以每个分隔符来分field,所以有重复分隔符的话,每个分隔符算一个field。

3、可以以 "-x N-M" 形式来指定切割一个范围内的字符串,其中x 可以为 b (bytes)、c(characters) 和 f(fields)。

如果需要多个不同范围,可以用 “," 隔开范围,默认不同范围之间输出是连续的,可以用 --output-delimiter 选项来分隔。

$ cat range_fields.txt
abcdefghijklmnopqrstuvwxyz
abcdefghijklmnopqrstuvwxyz
abcdefghijklmnopqrstuvwxyz
abcdefghijklmnopqrstuvwxy
$ cut -c-2,4-5 range_fields.txt --output-delimiter ","      # 只输出前2个字符串以及第4~5个字符,以逗号隔开。
ab,de
ab,de
ab,de
ab,de

二 sed

1、 sed 是一种 stream editor,常用来进行文本替换。

2、sed 接受 stdin 或 文件名 作为输入,输出至 stdout。

cat file | sed 's/pattern/replace_string/'       # 使用管道作为输入
$ sed 's/text/replace/' file > newfile           # 使用重定向保存结果
$ mv newfile file
$ sed -i 's/text/replace/' file                  # 使用 -i 参数直接将修改写入源文件

3、需要注意的是,上面的命令只会替换每行第一次遇到的匹配字符串,如果想替换每行中全部匹配字符串,需加参数 g。

$ sed 's/pattern/replace_string/g' file
也可以从第N次出现时开始替换(还是以行为单位):
$ cat cut.test
1 2 2 2
1  2 2
1   2 2
$ sed 's/2/3/2g' cut.test
1 2 3 3
1  2 3
1   2 3
3、 在上述的sed命令中是作为分隔符使用的,我们可以用任何字符作为分隔符,当分隔符出现在pattern中时,可以用 "\" 转义。
sed 's:text:replace:g'           # ":" 作为分隔符
sed 's|text|replace|g'           # "|" 作为分隔符
4、使用 sed '/pattern/d'  filename 来删除匹配字符串。
$ sed '/^$/d' file               # 删除空白行
5、可以使用 '&' 标记来表示前面匹配的字符串,比如:
$ echo this is an example | sed 's/\w\+/[&]/g'            # 这里的 \w 代表一个word中的字母,详见备注【1】,\+表示重复前面,其实属于正则表达式。
[this] [is] [an] [example]
6、可以使用 '\1' 标记来表示前面匹配字符串的子串。
$ echo this is digit 7 in a number | sed 's/digit \([0-9]\)/\1/'
this is 7 in a number
上诉命令用 7 替换了 digit 7,子串是7。\(pattern)\ 用来匹配子串,对于第一个匹配子串对应的标记是 '\1',同理第二个匹配子串对应的是 '\2'。
$ echo seven EIGHT | sed 's/\([a-z]\+\) \([A-Z]\+\)/\2 \1/'
EIGHT seven
([a-z]\+\)
匹配第一个word, \([A-Z]\+\) 匹配第二个word,\1 和 \2 用来引用他们。
7、多个表达式的联合,下面两种方式是一样的:

$ sed 'expression' | sed 'expression'
$ sed 'expression; expression'

三 awk

1、awk 的格式如下:
awk ' BEGIN{ print "start" } pattern { commands } END{ print "end" } file
分为3块,BEGIN、END和一个带有正则匹配的common statements block,三则均可选。
其中 BEGIN中的块在 awk 最开始处理时执行一次,然后对从 file / stdin 中读入的每一行执行 pattern {command};文件读完执行END块。

2、awk中的特殊变量有 NR (number of records,即当前行)、NF(number of fields,即当前列,默认空格分隔)、$0(当前行的内容)、$1(当前列的第一个field,$n类推)

$ echo -e "line1 f2 f3\nline2 f4 f5\nline3 f6 f7" | \
awk '{
print "Line no:"NR",No of fields:"NF, "$0="$0, "$1="$1,"$2="$2,"$3="$3
}'
Line no:1,No of fields:3 $0=line1 f2 f3 $1=line1 $2=f2 $3=f3
Line no:2,No of fields:3 $0=line2 f4 f5 $1=line2 $2=f4 $3=f5
Line no:3,No of fields:3 $0=line3 f6 f7 $1=line3 $2=f6 $3=f7
3、使用 -v 选项传递外部参数。
$ VAR=10000
$ echo | awk -v VARIABLE=$VAR'{ print VARIABLE }'      # 可以在块中直接引用变量,而不用加$
10000
4、使用 getline 来读取行。

$ seq 5 | awk 'BEGIN { getline; print "Read ahead first line", $0 } {
print $0 }'
Read ahead first line 1
2
3
4
5
5、使用条件来选取行

$ awk 'NR < 5' # Line number less than 5
$ awk 'NR==1,NR==4' #Line numbers from 1-5
$ awk '/linux/' # Lines containing the pattern linux (we can specify
regex)
$ awk '!/linux/' # Lines not containing the pattern linux
6、默认分隔符是空格,可以使用 -F 来指定其他值。

$ awk -F: '{ print $NF }' /etc/passwd
Or:
awk 'BEGIN { FS=":" } { print $NF }' /etc/passwd
可以使用 OFS='delimiter' 来指定输出时的分隔符

备注:

【1】Regular expressions 分为三种 the basic  component of regular  expressions (regex), the POSIX character class, and meta characters。

regex是大家常见打那种,比如 ^、$、.、[]、[^]、[-]、?、+、*、()、{n}、{n,}、{n,m}、|、\ 等。

POSIX character class是类似于 [:...:] 的,比如 [:alnum:]、[:alpha:]、[:blank:]、[:digit:] 、[:lower:]、[:upper:] 、[:punct:]、[:space:] 等。

以上两种如果支持正则表达式,则一定支持,但是 meta characters 则不是。

Meta characters are a type of Perl-style regular expression that is supported by a subset of  text processing utilities. Not all of the utilities will support the following notations. 

Meta characters
RegexDescriptionExample
\bWord boundary  "\bcool\b" matches only "cool" not  "coolant".
\BNon-word boundary  "cool\B" matches "coolantand" not "cool"
\dSingle digit character  "b\db" matches "b2b" not "bcb".
\DSingle non-digit  "b\Db" matches "bcb" not "b2b".
\wSingle word character(alnum and _)  "\w" matches "1" or "a" not “&”
\WSingle non-word character  "\w" matches "&" not "1" or "a"
\nNewline  "\n" Matches a new line
\sSingle whitespace  "x\sx" matches "xx" not "xx"
\SSingle non-space "x\Sx" matches "xkx" not "xx".
\rCarriage return  "\r" matches carriage return.
以上内容摘自《Linux Shell Scripting Cookbook》,有意研究也可参考维基百科Regular expre你ssion。 

【2】 关于sed中到底什么时候哪些字符需要前面加 '\' 来进行转义,可以参考这个stackexchange上得这个回答What characters do I need to escape when using
sed in a sh script? 。Gilles得回答感觉挺好,首先要注意 shell (这里我们一般用 单引号 ' 来将表达式引住),其次是注意BRE:$.*[\]^
,这些字符在BRE中有特别含义,引用时需转义;另外还有其他情况,可以参考回答,挺详细的。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  linux sed awk regex cut