流编辑器sed
sed与grep一样,都起源于老式的ed编辑器,因其是一个流编辑器(stream editor)而得名。与vi等编辑器不同,sed是一种非交互式编辑器(即用户不必参与编辑过程),它使用预先设定好的编辑指令对输入的文本进行编辑,完成之后再输出编辑结果。
sed工作时,首先读取文本中的第1行,将其放入一个被称为模式空间的临时缓冲区内。然后再读取第一条编辑指令,使用指令中定义的模式和行号查找、编辑文本。(这些操作都是针对读入到模式空间里的文本进行的操作,原文本的内容不受影响)完成编辑后,将结果输出并读取下一行,重复这个过程直到文本结束。除了模式空间之外,sed还使用了一个被称为保留空间的临时缓冲区,保留空间通常用于暂存编辑内容。
sed通常用来对多个文件或命令输出进行重复处理,以达到简化操作的目的。它是一个非常重要的文本过滤工具。
一、sed基本格式
- 命令格式:
sed [option] command input-file
sed [option] –f script-file input-file
上面的命令格式中,展示了sed的两种使用方法。第一种调用方法中,将编辑指令直接放在选项后面,这是最为常见的一种。当执行一些较为复杂的编辑操作时,可能使用的编辑命令会很长,这时为了便于阅读,通常将编辑指令放入一个脚步文件中,通过第2种方法来调用sed编辑文本。
- 常用选项:
选项用于指定编辑行为、打印设置等,常用的选项如下:
n:不输出所有行,默认情况是输出所有行。
e:允许在该选项后面加一条新的编辑指令。当有多条编辑指令时,应该使用该选项逐一添加,如果编辑指令只有一条,可以不使用该选项。
f:用于指定装有编辑指令的脚本文件。
h:输出sed的帮助信息。
- 常用的定位方式:
使用sed编辑文本时,应该向其指出要编辑的位置信息,通常使用一个行号或指定一个行号范围,也可以使用正则表达式对要编辑的文本进行模式匹配。常见的操作如下。
n:表示行号为n的行。
m,n:表示一个行号的范围,从第m行到第n行。
m,n!:排除第m行到第n行。
/pattern/:表示匹配pattern的所有行。
/pattern1/pattern2/:表示匹配pattern1和pattern2的所有行(需要使用选项e将两个模式隔开)。
/pattern/,~n:从匹配pattern的行开始,向后的n行(即包括匹配行在内,一共n行)。
/pattern/,+n:从匹配pattern的行开始,加上其后面的n行(即包括匹配行在内,一共n+1行)。
n,/pattern/:表示从第n行开始到匹配pattern之内的所有行。
- 常用的编辑指令:
使用sed编辑文本时,必须要使用对文本进行操作的指令(称为编辑指令),使用编辑指令可以对文本执行修改、删除和替换等操作。常用的编辑指令及说明如下。
p:将指定的行输出到标准输出。
P:将模式空间中第一个换行符“\n”之前的文本输出到标准输出(选项为大写P)。
=:输出匹配模式所在的行号。
d:移除模式空间中的行并读取下一行。
D:删除模式空间中最后一个换行符之前的文本。如果模式空间为空,则将下一行文本读取到模式空间中。
a\text:在指定的行后面加入新的文本信息text。
i\text:在指定行前面加入新的文本信息text。
c\text:使用新文本信息text替换定位行。
r file:从文件file中读取文本。
w file:将结果写入file文件中。
s/pattern1/pattern2/flag:将与模式pattern1匹配的文本用pattern2替换。默认情况下,只替换第一次匹配到的内容。指令之后的/分隔符可以使用任意字符替代。
n:如果没有禁止默认输出所有行功能(即没有使用选项n),则将模式空间的内容输出到标准输出。如果禁止默认输出功能,就读取下一行文本并替换模式空间中的文本。
N:在当前模式空间中的文本末尾加上换行符\n,并读取下一行文本追加到换行符之后。
!command:对没有被定位的行使用!之后的command编辑指令。
y/pattern1/pattern2/:将与模式pattern1匹配的文本用pattern替换,pattern1和pattern2的字符长度应该相等。
l:将模式空间的文本和控制字符以肉眼可见的方式输出到标准输出。
{sub_command}:执行大括号内的子命令或子命令组。
g:清除模式空间并将保留空间的文本放进模式空间(即模式空间<保留空间)
G:将保留空间的文本追加到模式空间的文本之后(即模式空间<<保留空间)
h:清除保留空间并将模式空间的文本放入保留空间(即模式空间>保留空间)
H:将模式空间的文本追加到保留空间的文本之后(即模式空间>>保留空间)
x:保留空间的文本和模式空间的文件进行互换。
Q:退出指令。使用q指令可以让sed立即退出,不再执行后面的操作。
在上面的编辑指令中,替换匹配模式指令s的flag选项通常向sed指示如何替换或替换成功后要进行的操作。常见的flag选项如下:
g:将所有匹配到的内容全部替换。
n:仅对行内第n次匹配到的内容进行替换。
p:如果进行了替换,就将模式空间的文本输出到标准输出。
w file:如果进行了替换,就将模式空间的文本写入文件file中。
一个编辑指令只能对指定位置进行一次编辑操作,如果要对指定位置执行多次编辑操作,可以使用大括号{}将多条编辑指令放入其中。而对多个位置进行多次编辑可以使用e选项添加多条编辑指令,也可以使用管道并配合多个sed命令。
- 常用的分支语句:
:label :标记点。标记一个位置以便于跳转语句跳转到指定位置。可以使用任何8个或少于8个字符的字符串来做标记点。
t label:测试指令,如果上一条替换指令成功执行,则转移到标记点label处继续执行。如果没有label,则转移到末尾。
b label:无条件转移到标记点label处继续执行。如果没有label,则转移到末尾。
#:一般用于脚本的注释。将#号后面的内容视为注释,sed将忽略后面的内容,直接执行下一行。如果出现在脚本的第1行,且后面是n(即#n),sed将不禁止默认地输出所有行。
使用了分支语句的编辑指令通常都很长,一般将这些指令放在脚本文件中,然后使用f选项调用sed。
二、显示和删除行
sed命令执行结束后,通常将结果输出到屏幕上,如果需要保存sed命令的输出结果,可以使用输出重定向的方法。
说明:通常将编辑指令放入单引号中,以便于阅读及屏蔽某些特殊字符。
1、显示行
显示行需要使用sed的编辑命令p,指定显示内容可以使用行号、行号范围、正则表达式等。
(1)使用数字3指定输出文本的第3行:
#使用数字3指定输出的行号 #由于sed默认输出所有行,因此使用选项n屏蔽掉默认的输出 [root@localhost zhu]# sed -n '3p' students 2721020321 Xuli Jiangsu Luolei 12/25/92 76 81 85 79 321 80
(2)输出指定的行时,也可以指定一个输出范围,例如输出第3行到第5行:
[root@localhost zhu]# sed -n '3,5p' students 2721020321 Xuli Jiangsu Luolei 12/25/92 76 81 85 79 321 80 2921020632 Xiayu Shanxi Hetao 03/26/93 78 86 92 78 334 84 2721010409 Liwei Sichuan tangwei 11/21/92 98 88 85 85 356 89
(3)大多时候可能我们并不知道要输出的具体行号,此时可以使用模式匹配的方式定位要输出的行。例如要输出所有辅导员是Tangwei的学生情况:
[root@localhost zhu]# sed -n '/[tT]angwei/p' students 2721010409 Liwei Sichuan tangwei 11/21/92 98 88 85 85 356 89 2921050313 Heli Xizang Tangwei 07/12/94 56 78 80 45 259 65
(4)可以同时使用行号和模式匹配来指定要输出的行。例如输出从第2行开始到匹配含有Hetao的行之间的所有文本:
[root@localhost zhu]# sed -n '2,/Hetao/p' students 2821020115 Liumin Henan lixia 05/14/94 78 65 59 78 280 70 2721020321 Xuli Jiangsu Luolei 12/25/92 76 81 85 79 321 80 2921020632 Xiayu Shanxi Hetao 03/26/93 78 86 92 78 334 84
(5)可以使用行首或行尾匹配来指定要输出的行。例如要查找所有2009年入学的学生情况:
[root@localhost zhu]# sed -n '/^29/p' students 2921020632 Xiayu Shanxi Hetao 03/26/93 78 86 92 78 334 84 2921050313 Heli Xizang Tangwei 07/12/94 56 78 80 45 259 65
(6)如果要查找某个匹配行的位置,可以不输出匹配行的内容,只输出匹配行的行号。例如要输出西藏的学生在哪行:
[root@localhost zhu]# sed -n '/Xizang/=' students 6
(7)也可以匹配一行,然后输出匹配行下面n行之内的所有行。例如含有Luolei的行和其后的1行内容:
[root@localhost zhu]# sed -n '/Luolei/,~2p' students 2721020321 Xuli Jiangsu Luolei 12/25/92 76 81 85 79 321 80 2921020632 Xiayu Shanxi Hetao 03/26/93 78 86 92 78 334 84
2、删除行
许多时候我们希望能够删除文本中的内容(类似于grep命令中的反转查找),此时可以使用编辑指令d删除匹配的行。
(1)删除所有2008年入学的学生信息:
#由于指令d会删除模式空间中的内容,因此可以不使用选项n [root@localhost zhu]# sed '/^28/d' students 2721020321 Xuli Jiangsu Luolei 12/25/92 76 81 85 79 321 80 2921020632 Xiayu Shanxi Hetao 03/26/93 78 86 92 78 334 84 2721010409 Liwei Sichuan tangwei 11/21/92 98 88 85 85 356 89 2921050313 Heli Xizang Tangwei 07/12/94 56 78 80 45 259 65 2721030227 Wangtao Yunnan Huli 03/21/93 87 76 69 88 320 80 执行上面的删除操作只是在模式空间里进行的,对students文件里内容没有影响 [root@localhost zhu]# cat students 2821020225 Liulu Sichuan Lixia 01/23/93 89 76 88 72 325 81 2821020115 Liumin Henan lixia 05/14/94 78 65 59 78 280 70 2721020321 Xuli Jiangsu Luolei 12/25/92 76 81 85 79 321 80 2921020632 Xiayu Shanxi Hetao 03/26/93 78 86 92 78 334 84 2721010409 Liwei Sichuan tangwei 11/21/92 98 88 85 85 356 89 2921050313 Heli Xizang Tangwei 07/12/94 56 78 80 45 259 65 2721030227 Wangtao Yunnan Huli 03/21/93 87 76 69 88 320 80 [root@localhost zhu]# sed -n '/^28/d' students [root@localhost zhu]#
这里匹配以28开头的所有文本都被删除了,如果使用n选项将不会有任何输出。
(2)在进行删除时,如果有多个要匹配的条件,此时可以配合使用e选项添加多个编辑指令。例如删除所有匹配lixia和Shanxi的行:
[root@localhost zhu]# sed -ne '/[Ll]ixia/d' -e '/Shanxi/d' -e p students 2721020321 Xuli Jiangsu Luolei 12/25/92 76 81 85 79 321 80 2721010409 Liwei Sichuan tangwei 11/21/92 98 88 85 85 356 89 2921050313 Heli Xizang Tangwei 07/12/94 56 78 80 45 259 65 2721030227 Wangtao Yunnan Huli 03/21/93 87 76 69 88 320 80
执行上面这条指令时,sed将会按选项e指定的编辑指令顺序依次执行。
(3)也可以像显示行那样,使用行号范围删除行。例如需要删除前3行:
[root@localhost zhu]# sed '1,3d' students 2921020632 Xiayu Shanxi Hetao 03/26/93 78 86 92 78 334 84 2721010409 Liwei Sichuan tangwei 11/21/92 98 88 85 85 356 89 2921050313 Heli Xizang Tangwei 07/12/94 56 78 80 45 259 65 2721030227 Wangtao Yunnan Huli 03/21/93 87 76 69 88 320 80
3、插入和修改文本
在指定的行进行插入时,可以使用编辑指令a和i,而替换行则使用编辑指令c。如果插入和替换的内容不止一行,可以在非最后一行使用反斜线“\”符号表示插入的内容并未结束。格式如下:
[指定的行或模式][aic\]
The first line.\
The second line.\
...
The last line.
在上面的格式中,要插入或替换的文本可以位于一行,但是必须用\n来指定换行的位置。编辑指令后的反斜线指定了文本的起始位置。除此之外,为了避免sed引起误解,通常将编辑指令和文本放入单引号中。
(1)例如想要在第1行后面插入新的一行:
[root@localhost zhu]# sed '1a\This is a new line.' students 2821020225 Liulu Sichuan Lixia 01/23/93 89 76 88 72 325 81 This is a new line. 2821020115 Liumin Henan lixia 05/14/94 78 65 59 78 280 70 2721020321 Xuli Jiangsu Luolei 12/25/92 76 81 85 79 321 80 2921020632 Xiayu Shanxi Hetao 03/26/93 78 86 92 78 334 84 2721010409 Liwei Sichuan tangwei 11/21/92 98 88 85 85 356 89 2921050313 Heli Xizang Tangwei 07/12/94 56 78 80 45 259 65 2721030227 Wangtao Yunnan Huli 03/21/93 87 76 69 88 320 80
注意:执行插入和修改行操作时,如果不使用行号和匹配模式指定要编辑的行,sed会编辑文本的每一行。
(2)也可以使用行首和行尾匹配来定位要插入新文本的位置。例如要在最后一行插入以个新行:
[root@localhost zhu]# sed '$a\This is a new line.' students 2821020225 Liulu Sichuan Lixia 01/23/93 89 76 88 72 325 81 2821020115 Liumin Henan lixia 05/14/94 78 65 59 78 280 70 2721020321 Xuli Jiangsu Luolei 12/25/92 76 81 85 79 321 80 2921020632 Xiayu Shanxi Hetao 03/26/93 78 86 92 78 334 84 2721010409 Liwei Sichuan tangwei 11/21/92 98 88 85 85 356 89 2921050313 Heli Xizang Tangwei 07/12/94 56 78 80 45 259 65 2721030227 Wangtao Yunnan Huli 03/21/93 87 76 69 88 320 80 This is a new line.
(3)如果使用的多行文本位于同一行,需要在每一个需要断行的位置加入换行符\n:
[root@localhost zhu]# sed '3a\The first line.\nThe second line.' students 2821020225 Liulu Sichuan Lixia 01/23/93 89 76 88 72 325 81 2821020115 Liumin Henan lixia 05/14/94 78 65 59 78 280 70 2721020321 Xuli Jiangsu Luolei 12/25/92 76 81 85 79 321 80 The first line. The second line. 2921020632 Xiayu Shanxi Hetao 03/26/93 78 86 92 78 334 84 2721010409 Liwei Sichuan tangwei 11/21/92 98 88 85 85 356 89 2921050313 Heli Xizang Tangwei 07/12/94 56 78 80 45 259 65 2721030227 Wangtao Yunnan Huli 03/21/93 87 76 69 88 320 80
(4)从上面几个示例可以看出,插入多行时命令可读性很差,因此通常将编辑指令和文本放入一个脚本文件内,通过f选项调用sed进行编辑。
例如使用编辑指令i在匹配Hetao的行前面插入多行内容:
[root@localhost zhu]# cat insert.sed /Hetao/i\ The first line.\ The second line.\ The last line. [root@localhost zhu]# sed -f insert.sed students 2821020225 Liulu Sichuan Lixia 01/23/93 89 76 88 72 325 81 2821020115 Liumin Henan lixia 05/14/94 78 65 59 78 280 70 2721020321 Xuli Jiangsu Luolei 12/25/92 76 81 85 79 321 80 The first line. The second line. The last line. 2921020632 Xiayu Shanxi Hetao 03/26/93 78 86 92 78 334 84 2721010409 Liwei Sichuan tangwei 11/21/92 98 88 85 85 356 89 2921050313 Heli Xizang Tangwei 07/12/94 56 78 80 45 259 65 2721030227 Wangtao Yunnan Huli 03/21/93 87 76 69 88 320 80
(5)如果要插入的是一个很长的文本,可以使用r指令将要插入的文本读取后再执行插入操作。例如要将文件ex中的文本插入到第3行之后:
[root@localhost zhu]# sed '3r ex' students 2821020225 Liulu Sichuan Lixia 01/23/93 89 76 88 72 325 81 2821020115 Liumin Henan lixia 05/14/94 78 65 59 78 280 70 2721020321 Xuli Jiangsu Luolei 12/25/92 76 81 85 79 321 80 The first line. The second line. The last line. 2921020632 Xiayu Shanxi Hetao 03/26/93 78 86 92 78 334 84 2721010409 Liwei Sichuan tangwei 11/21/92 98 88 85 85 356 89 2921050313 Heli Xizang Tangwei 07/12/94 56 78 80 45 259 65 2721030227 Wangtao Yunnan Huli 03/21/93 87 76 69 88 320 80
由于使用r指令是直接将一个文件中的文本插入到另一个文本,因此不需要在每一行的结尾加上反斜线。
(6)如果要使用sed替换整行,通常使用编辑指令c。下面是一个使用编辑指令c修改行的示例,首先匹配所有以27开头的行,然后使用c指令将所有匹配到的行替换成新的内容,最后将输出结果重定向到文件file1中:
[root@localhost zhu]# cat modify.sed /^27/c\ This line was modified. [root@localhost zhu]# sed -f modify.sed students >file1 [root@localhost zhu]# cat file1 2821020225 Liulu Sichuan Lixia 01/23/93 89 76 88 72 325 81 2821020115 Liumin Henan lixia 05/14/94 78 65 59 78 280 70 This line was modified. 2921020632 Xiayu Shanxi Hetao 03/26/93 78 86 92 78 334 84 This line was modified. 2921050313 Heli Xizang Tangwei 07/12/94 56 78 80 45 259 65 This line was modified.
提示:在定位的位置插入新行时,只能使用行号和匹配模式指定要编辑的行,不能指定一个范围。
4、替换文本和其他编辑指令
sed提供了两个用于替换文本的编辑指令s和y,它们的使用方法相似但功能却不同。
它们的格式如下:
s/pattern1/pattern2/flag
y/pattern1/pattern2/
s指令将匹配到的pattern1用pattern2替换,y指令的功能与其很相似,不同的是y指令要求匹配的模式与用来替换的文本的字符数长度必须相等。
示例文本students2:
[root@localhost zhu]# cat students2 2821020225##Liulu$$0::A**B&&0\\ 2821020115##Liumin$$B::C**0&&0\\ 2721020321##Xuli$$0::0**B&&D\\ 2921020632## Xiayu$$0::0**0&&0\\ 2721010409##Liwei$$C::0**0&&0\\ 2921050313##Heli$$A::0**A&&B\\ 2721030227## Wangtao$$B::B**C&&0\\
(1)执行替换操作
首先需要整理这个文件,使用制表符Tab替换所有学号和姓名中间的井号#。要将所有#都替换掉,s编辑指令的flag选项应该使用g:
#使用指令s的flag选项g执行全文替换 #使用反斜杠屏蔽井号的特殊意义 #命令中空白为Tab制表符 [root@localhost zhu]# sed 's/\#\#/ /g' students2 | tee students2.1 2821020225 Liulu$$0::A**B&&0\\ 2821020115 Liumin$$B::C**0&&0\\ 2721020321 Xuli$$0::0**B&&D\\ 2921020632 Xiayu$$0::0**0&&0\\ 2721010409 Liwei$$C::0**0&&0\\ 2921050313 Heli$$A::0**A&&B\\ 2721030227 Wangtao$$B::B**C&&0\\
提示:在命令提示符中输入制表符Tab的方法是先按住Ctrl键,再按v键,然后松开v键,再按Tab键松开Ctrl键,最后松开Tab键。
(2)继续使用Tab将其他的字符替换掉:
[root@localhost zhu]# cat replace.sed s/\$\$/ /g s/\:\:/ /g s/\*\*/ /g s/\&\&/ /g s/\\*$//g [root@localhost zhu]# sed -f replace.sed students2.1 | tee students2.2 2821020225 Liulu 0 A B 0 2821020115 Liumin B C 0 0 2721020321 Xuli 0 0 B D 2921020632 Xiayu 0 0 0 0 2721010409 Liwei C 0 0 0 2921050313 Heli A 0 A B 2721030227 Wangtao B B C 0
上面的这个示例中,为了保证对齐,在替换姓名后面的$符号时,使用了两个Tab。脚本最后一行,使用了"s/\\*$//g”,其中“\\*$”表示在行尾匹配一个或多个“\”,没有指定用任何字符进行替换,就表示需要删除行尾的“\”符号。
(3)有时需要查看一些肉眼无法看见的控制字符,此时可以使用编辑指令l以肉眼可以看见的方式输出控制字符。例如:
[root@localhost zhu]# sed -n '1,3l' students2.2 2821020225\tLiulu\t\t0\tA\tB\t0$ 2821020115\tLiumin\t\tB\tC\t0\t0$ 2721020321\tXuli\t\t0\t0\tB\tD$
(4)对指定行之外的行或模式匹配之外的行进行操作,此时可以使用“!”指定需要排除的行。
例如显示除了行号为1 之外的行:
[root@localhost zhu]# sed -n '1!p' students2.2 2821020115 Liumin B C 0 0 2721020321 Xuli 0 0 B D 2921020632 Xiayu 0 0 0 0 2721010409 Liwei C 0 0 0 2921050313 Heli A 0 A B 2721030227 Wangtao B B C 0
(5)在一行执行多次编辑,此时将多个编辑指令放入大括号{}内。例如将实践课成绩中含义A或B的先输出,其他的后输出:
[root@localhost zhu]# sed -n '/^2/{/[AB]/p; /[AB]/!H; $g; $p}' students2.2 2821020225 Liulu 0 A B 0 2821020115 Liumin B C 0 0 2721020321 Xuli 0 0 B D 2921050313 Heli A 0 A B 2721030227 Wangtao B B C 0 2921020632 Xiayu 0 0 0 0 2721010409 Liwei C 0 0 0
对上面命令的解释:首先匹配以2开头的行,如果匹配,则执行{}内的语句块(大括号内用分号;将各个独立的语句行分开)。当一条匹配行被送进大括号时,如果该行有A或B则打印;如果该行没有A或B则将该行追加到保留空间内;如果该行是最后一行则用保留空间的文本替换模式空间的文本,如果不是最后一行则匹配下一行;$p打印被前面的指令$g替换后的模式空间的文本。
由于保留空间的第1行为空,且使用的是H指令(追加到保留空间),因此在输出中第6行为空。
将上面这条命令拆开等同于:
[root@localhost zhu]# sed -ne '/[AB]/p' -e '/[AB]/!H' -e '$g' -e '$p' students2.2 2821020225 Liulu 0 A B 0 2821020115 Liumin B C 0 0 2721020321 Xuli 0 0 B D 2921050313 Heli A 0 A B 2721030227 Wangtao B B C 0 2921020632 Xiayu 0 0 0 0 2721010409 Liwei C 0 0 0
(6)将A B C D转换为数字:
[root@localhost zhu]# sed -e 's/A/85/g' -e 's/B/75/g' -e 's/C/60/g' -e 's/D/50/g' students2.2 | tee students2.3 2821020225 Liulu 0 85 75 0 2821020115 Liumin 75 60 0 0 2721020321 Xuli 0 0 75 50 2921020632 Xiayu 0 0 0 0 2721010409 Liwei 60 0 0 0 2921050313 Heli 85 0 85 75 2721030227 Wangtao 75 75 60 0
(7)使用s指令替换文本时,可以使用符号&(与单词and读音相同)表示匹配的文本行本身。例如使用s指令匹配并插入内容:
[root@localhost zhu]# cat bj Welcome to beijing! [root@localhost zhu]# C2=Welcome [root@localhost zhu]# sed -n "s/$C2/Hello! &/p" bj Hello! Welcome to beijing!
注意:由于单引号会忽略变量引用符号的引用功能,因此如果在sed编辑指令中使用了变量,就不能将编辑指令放入单引号内。
(8)相对于s而言,替换指令y使用相对较少。
sed "y/123/abc/" file
上述替换规律:把file中的1替换成a;2替换成b;3替换成c。注意其对应关系。
(9)编辑命令y的一个重要用途就是用来转换大小写,例如:
[root@localhost zhu]# cat bj Welcome to beijing! [root@localhost zhu]# sed 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/' bj WELCOME TO BEIJING!
5、处理文本中的控制字符
许多人比较喜欢在Windwos系统中使用文本编辑器编写脚本(例如UltrEdit编辑器等),然后将编写好的脚本使用共享、SFTP等方式传递到Linux系统上执行。这时可能这些文本中存在一些控制字符,这些控制字符可能会影响脚步的运行或文档的使用(Linux系统不能识别Windows中的部分字符)。因此在使用这些文本之前应该删除这些控制字符。
要删除文本中的控制字符,首先应该查看文本中的控制字符。通常可以使用cat命令的v选项查看这些肉眼看不见的控制字符:
[root@localhost test]# cat -v hello.sh #!/bin/bash^M #this is a test script^M ^M echo "Hello"^M
在上面的示例中,“^M”就是一个控制字符,删除这些控制字符的思路是使用s将其删除,但在删除之前必须要能产生一个相同的控制字符。
此处以产生“^M”控制字符为例:在终端下先按住Ctrl键,然后再按下V键,此时终端上将不会有任何字符显示。然后松开V键,并按下M键,此时可以看到屏幕上已经产生了控制字符^M,最后松开Ctrl键和M键即可完成输入。
使用如下命令删除文本中的控制字符:
[root@localhost test]# sed 's/^M//g' hello.sh >hello1.sh [root@localhost test]# cat -v hello1.sh #!/bin/bash #this is a test script echo "Hello"
示例命令中的^M一定要手动输入,不可复制粘贴。