一、按列合并多个文件
1.1 paste
$ paste file1 file2 file3 ...
例:
$ cat file1.txt
1
2
3
4
5
$ cat file2.txt
slynux
gnu
bash
hack
$ paste file1.txt file2.txt
1 slynux
2 gnu
3 bash
4 hack
5
默认的分隔符是制表符,也可以用-d指定分隔符:
$ paste file1.txt file2.txt -d ","
1,slynux
2,gnu
3,bash
4,hack
5,
二、打印文件或行中的第n 个单词或列
2.1 打印第5列:
$ awk '{ print $5 }' filename
2.2 可以打印多列数据并在各列间插入指定的字符串
如果要打印当前目录下各文件的权限和文件名,可以使用下列命令:
$ ls -l | awk '{ print $1 " : " $8 }'
-rw-r--r-- : delimited_data.txt
-rw-r--r-- : obfuscated.txt
-rw-r--r-- : paste1.txt
-rw-r--r-- : paste2.txt
三、打印指定行或模式之间的文本
我们有时候可能需要根据某些条件打印文件的一部分,比如由指定行号或起止模式所匹配的文本范围。
3.1 打印从M行到N行之间的文本
$ awk 'NR==M, NR==N' filename
3.2 打印位于模式start_pattern与end_pattern之间的文本
$ awk '/start_pattern/, /end_pattern/' filename
例如:
$ cat section.txt
line with pattern1
line with pattern2
line with pattern3
line end with pattern4
line with pattern5
$ awk '/pa.*3/, /end/' section.txt
line with pattern3
line end with pattern4
awk中使用的模式为正则表达式。
四、以逆序形式打印行
4.1 tac
tac file1 file2 ...
例如
$ seq 5 | tac
5
4
3
2
1
tac命令默认使用\n作为行分隔符。但我们也可以用选项-s指定其他分隔符。
$ echo "1,2" | tac-s,
2
1
4.1 awk
seq 9 | \
awk '{ lifo[NR]=$0 } \
END { for(lno=NR;lno>-1;lno--){ print lifo[lno]; }
}'
五、解析文本中的电子邮件地址和URL
5.1 匹配电子邮件地址
能够匹配电子邮件地址的正则表达式如下:
[A-Za-z0-9._]+@[A-Za-z0-9.]+\.[a-zA-Z]{2,4}
例如
$ cat url_email.txt
this is a line of text contains,<email> #slynux@slynux.com.
</email> and email address, blog "http://www.google.com",
test@yahoo.com dfdfdfdddfdf;cool.hacks@gmail.com<br />
<a href="http://code.google.com"><h1>Heading</h1>
因为用到了扩展正则表达式(例如+),所以得使用egrep命令:
$ egrep -o '[A-Za-z0-9._]+@[A-Za-z0-9.]+\.[a-zA-Z]{2,4}' url_email.txt
slynux@slynux.com
test@yahoo.com
cool.hacks@gmail.com
5.2 匹配HTTP URL
匹配HTTP URL的egrep正则表达式如下:
http://[a-zA-Z0-9.]+\.[a-zA-Z]{2,3}
例如:
$ egrep -o "http://[a-zA-Z0-9.]+\.[a-zA-Z]{2,3}" url_email.txt
http://www.google.com
http://code.google.com
六、删除文件中包含特定单词的句子
先创建一个包含替换文本的文件。例如:
$ cat sentence.txt
Linux refers to the family of Unix-like computer operating systems
that use the Linux kernel. Linux can be installed on a wide variety
of computer hardware, ranging from mobile phones, tablet computers
and video game consoles, to mainframes and supercomputers. Linux is
predominantly known for its use in servers.
我们的目标是删除包含mobile phones的句子。可以用下面的sed语句来实现
$ sed 's/ [^.]*mobile phones[^.]*\.//g' sentence.txt
Linux refers to the family of Unix-like computer operating systems
that use the Linux kernel. Linux is predominantly known for its use
in servers.
sed的正则表达式s/ [^.]mobile phones[^.].//g采用的格式为s/substitution_pattern/replacement_string/g。它将与substitution_pattern相匹配的每一处内容都用replacement_string替换掉。
本例中的substitution_pattern是用来匹配整句文本的正则表达式。文件中的每一句话都是以空格开头,以.结尾。正则表达式要匹配内容的格式就是:空格+若干文本+需要匹配的字符串+若干文本+句点。一个句子中除了作为分隔符的句点之外,可以包含任意字符。因此需要使用[^.],该模式可以匹配除句点之外的任意字符。表示之前的字符可以出现任意多次。用来匹配文本的mobile phones被放置在两个 [^.] 之间。每一个匹配的句子均被//替换(注意,/与/之间没有任何内容)。
七、对目录中的所有文件进行文本替换
假设我们希望将所有.cpp文件中的Copyright替换成Copyleft:
find . -name *.cpp -print0 | xargs -I{} -0 sed -i 's/Copyright/Copyleft/g' {}
我们使用find命令在当前目录(.)下查找所有的.cpp文件。它使用-print0打印出以\0作为分隔符的文件列表(这可以避免文件名中的空格所带来的麻烦)。然后使用管道将文件列表传递给xargs,后者将文件名作为sed的参数,通过sed修改文件内容。
find有一个选项-exec,它可以对查找到的每个文件执行命令。我们可以使用该选项实现同样的效果或是改用下列命令
$ find . -name *.cpp -exec sed -i 's/Copyright/Copyleft/g' \{\} \;
八、文本切片与参数操作
替换变量内容中的部分文本
$ var="This is a line of text"
$ echo ${var/line/REPLACED}
This is a REPLACED of text"
单词line被替换成了REPLACED。
我们可以通过指定字符串的起始位置和长度来生成子串,其语法如下
${variable_name:start_position:length}
下面的命令可以打印出第5个字符之后的内容:
$ string=abcdefghijklmnopqrstuvwxyz
$ echo ${string:4}
efghijklmnopqrstuvwxyz
从第5个字符开始,打印8个字符:
$ echo ${string:4:8}
efghijkl
字符串起始字符的索引从0开始。从后向前计数,字符串末尾字符的索引为-1。如果-1出现在括号内,那么(-1)表示的就是最后一个字符的索引:
echo ${string:(-1)}
z
$ echo ${string:(-2):2}
yz