如何在Linux上使用sed命令
听起来可能很疯狂,但是Linux sed
command是没有界面的文本编辑器。您可以从命令行使用它来处理文件和流中的文本。我们将向您展示如何利用其功能。
sed的力量
这 sed
命令有点像国际象棋:学习基础知识需要一个小时,而掌握基础知识则需要一辈子(或者至少需要大量练习)。我们将向您展示各主要类别中的一些开放性技巧 sed
功能。
sed
是用于管道输入或文本文件的流编辑器。但是,它没有交互式的文本编辑器界面。相反,您将提供指示信息以使其在文本中有效。所有这些都可以在Bash和其他命令行Shell中使用。
和 sed
您可以执行以下所有操作:
- 选择文字
- 替代文字
- 在文本中添加行
- 删除文字行
- 修改(或保留)原始文件
我们已经构造了示例,以介绍和演示概念,而不是提出最糟糕(且平易近人)的方法 sed
命令。但是,模式匹配和文本选择功能 sed
严重依赖于正则表达式(regexes)。您需要对这些内容有所了解,才能从中获得最大的收益 sed
.
有关的:如何在Linux上使用正则表达式(regexes)
一个简单的例子
首先,我们将使用 回声
发送一些文本到 sed
通过管道,并有 sed
替换文本的一部分。为此,我们键入以下内容:
回声howtogonk | sed's / gonk / geek /'
这 回声
命令将“ howtogonk”发送到 sed
,然后应用我们的简单替换规则(“ s”代表替换)。sed
在输入文本中搜索第一个字符串的出现,并将所有匹配项替换为第二个。
字符串“ gonk”被替换为“ geek”,新的字符串被打印在终端窗口中。
替代可能是最常见的用法 sed
。但是,在我们更深入地研究替代之前,我们需要知道如何选择和匹配文本。
选择文字
我们的示例将需要一个文本文件。我们将使用其中包含选自塞缪尔·泰勒·科尔里奇(Samuel Taylor Coleridge)的史诗《远古水手的降世》的诗句。
我们输入以下内容以了解它 较少的
:
少coleridge.txt
要从文件中选择一些行,我们提供要选择的范围的开始和结束行。单个数字选择该行。
要提取第一到第四行,我们输入以下命令:
sed -n'1,4p'coleridge.txt
注意之间的逗号 1
和 4
。这 p
表示“打印匹配的行”。默认,sed
打印所有行。我们会在文件中看到所有文本,其中匹配的行会打印两次。为防止这种情况,我们将使用 -n
(quiet)选项可取消显示不匹配的文本。
我们更改行号,以便我们可以选择其他经文,如下所示:
sed -n'6,9p'coleridge.txt
我们可以使用 -e
(表达式)选项进行多项选择。通过两个表达式,我们可以选择两个经文,如下所示:
sed -n -e'1,4p'-e '31,34p'coleridge.txt
如果我们减少第二个表达式中的第一个数字,我们可以在两个经文之间插入一个空格。我们输入以下内容:
sed -n -e'1,4p'-e '30,34p'coleridge.txt
我们也可以选择一条起跑线并告诉 sed
单步执行文件并每隔第五行打印交替的行,或者跳过任何数量的行。该命令与我们上面用来选择范围的命令相似。但这一次,我们将使用波浪号(~
),而不是用逗号分隔数字。
第一个数字表示起始行。第二个数字告诉 sed
我们要在起跑线之后的哪几行。数字2表示每隔第二行,数字3表示每隔三行,依此类推。
我们输入以下内容:
sed -n'1〜2p'coleridge.txt
您将不会总是知道要查找的文本在文件中的位置,这意味着行号不会总是很有帮助。但是,您也可以使用 sed
选择包含匹配文本模式的行。例如,让我们提取所有以“ And”开头的行。
尖号(^
)代表该行的开头。我们将搜索词括在正斜杠(/
)。我们还会在“与”之后加上一个空格,因此结果中将不会包含诸如“ Android”之类的字词。
读 sed
脚本一开始可能会有些困难。这 / p
意味着“打印”,就像我们上面使用的命令一样。但是,在以下命令中,正斜杠位于其前面:
sed -n'/ ^和/ p'coleridge.txt
从文件中提取以“ And”开头的三行,并为我们显示。
换人
在第一个示例中,我们向您展示了以下基本格式 sed
代换:
回声howtogonk | sed's / gonk / geek /'
这 s
告诉 sed
这是一个替代。第一个字符串是搜索模式,第二个字符串是我们要用来替换匹配文本的文本。当然,与所有Linux一样,细节在于魔鬼。
我们键入以下内容,将所有出现的“天”更改为“周”,并给水手和信天翁更多的时间绑定:
sed -n's / day / week / p'coleridge.txt
在第一行中,仅第二次出现的“ day”被更改。这是因为 sed
每行第一场比赛后停止。我们必须在表达式的末尾添加“ g”,如下所示,以执行全局搜索,以便处理每一行中的所有匹配项:
sed -n's / day / week / gp'coleridge.txt
这与第一行中的四个匹配。因为第一个单词是“ Day”, sed
是区分大小写的,它不认为该实例与“ day”相同。
我们输入以下内容,并添加 一世
表达式末尾的命令以表示不区分大小写:
sed -n's / day / week / gip'coleridge.txt
这可行,但是您可能并不总是希望对所有内容都启用不区分大小写的功能。在这些情况下,您可以使用正则表达式组来添加特定于模式的不区分大小写。
例如,如果我们将字符括在方括号([]
),它们被解释为“此字符列表中的任何字符”。
我们输入以下内容,并在组中包括“ D”和“ d”,以确保其与“ Day”和“ day”都匹配:
sed -n's / [Dd] ay / week / gp'coleridge.txt
我们还可以将替换限制在文件的各个部分。假设我们的档案在第一节经文中包含奇怪的空格。我们可以使用以下熟悉的命令来查看第一节经文:
sed -n'1,4p'coleridge.txt
我们将搜索两个空格,并用一个空格代替。我们将在全球范围内执行此操作,以便在整个生产线上重复执行该操作。明确地说,搜索模式是空格,星号(*
),并且替换字符串是单个空格。这 1,4
将替换限制在文件的前四行。
我们将所有这些放到以下命令中:
sed -n'1,4 s / * / / gp'coleridge.txt
这很好用!搜索模式在这里很重要。星号(*
)表示零个或多个前面的字符,它是一个空格。因此,搜索模式正在寻找一个或多个空格的字符串。
如果我们将单个空格替换为多个空格的任意序列,则会将文件恢复为常规间距,每个单词之间都应有一个空格。在某些情况下,这也可以将单个空格替换为单个空格,但这不会产生任何不利影响-我们仍将获得理想的结果。
如果输入以下内容并将搜索模式缩小到一个空格,您将立即看到为什么必须包含两个空格的原因:
sed -n'1,4 s / * / / gp'coleridge.txt
由于星号与零个或多个前一个字符匹配,因此它会将不是空格的每个字符都视为“零空格”,并对其进行替换。
但是,如果我们在搜索模式中包含两个空格,sed
在应用替换之前,必须至少找到一个空格字符。这样可以确保非空格字符保持不变。
我们使用 -e
(表达式),我们之前使用过,这使我们可以同时进行两个或多个替换:
sed -n -e's / motion / flutter / gip'-e's / ocean / gutter / gip'coleridge.txt
如果使用分号(;
)来分隔两个表达式,如下所示:
sed -n's / motion / flutter / gip; s / ocean / gutter / gip'coleridge.txt
当在以下命令中将“ day”替换为“ week”时,表达式“ day a-day”中的“ day”实例也被替换:
sed -n's / [Dd] ay / week / gp'coleridge.txt
为避免这种情况,我们只能在与另一个模式匹配的行上尝试替换。如果我们修改命令以使其在开始时具有搜索模式,则仅考虑在与该模式匹配的行上进行操作。
我们输入以下内容以使匹配模式成为单词“ after”:
sed -n'/ after / s / [Dd] ay / week / gp'coleridge.txt
这给了我们我们想要的回应。
更复杂的替代
让我们给Coleridge一个休息和使用的机会 sed
从中提取名称 等/密码
文件。
执行此操作的方法比较短(稍后会详细介绍),但是在这里我们将使用较长的方法来演示另一个概念。可以对搜索模式中的每个匹配项目(称为子表达式)进行编号(最多9个项目)。然后,您可以在自己的电话中使用这些数字sed
命令以引用特定的子表达式。
您必须将子表达式括在括号中[()
]以使其正常工作。括号中还必须加上反斜杠(\
),以防止它们被视为正常字符。
为此,您将键入以下内容:
sed's / \([^:] * \)。* / \ 1 /'/ etc / passwd
让我们来分解一下:
sed的/
: 这sed
命令和替换表达式的开头。\(
: 开头括号[(
]括住子表达式,并以反斜杠(\
).[^:]*
: 搜索词的第一个子表达式在方括号中包含一组。尖号(^
)在组中使用时表示“不是”。组是指不是冒号的任何字符(:
)将被视为匹配项。\)
: 右括号[)
]和前面的反斜杠(\
)..*
: 第二个搜索子表达式的意思是“任意字符和任意数量的字符”。/\1
: 表达式的替换部分包含1
前面加一个反斜杠(\
)。这表示与第一个子表达式匹配的文本。/'
: 右斜杠(/
)和单引号('
)终止sed
命令。
这一切都意味着我们将查找不包含冒号的任何字符串(:
),这将是匹配文本的第一个实例。然后,我们在该行中搜索其他内容,这将是匹配文本的第二个实例。我们将用与第一个子表达式匹配的文本替换整行。
每行 / etc / passwd
文件以冒号结尾的用户名开头。我们将所有内容匹配到第一个冒号,然后将该值替换为整行。因此,我们隔离了用户名。
接下来,我们将第二个子表达式放在括号中[()
],因此我们也可以按数字进行引用。我们还将替换 \1
和 \2
。现在,我们的命令将用第一个冒号中的所有内容替换整个行(:
)到该行的末尾。
我们输入以下内容:
sed's / \([^:] * \)\(。* \)/ \ 2 /'/ etc / passwd
这些小的更改使命令的含义反转,除用户名外,我们获得了所有内容。
现在,让我们看一下执行此操作的快速简便的方法。
我们的搜索词来自第一个冒号(:
)到该行的末尾。因为我们的替换表达式为空(//
),我们不会将匹配的文本替换为任何内容。
因此,我们键入以下内容,将第一个冒号中的所有内容都切掉(:
)到该行的末尾,仅保留用户名:
sed的s /:.*//“ / etc / passwd
让我们看一个示例,在该示例中,我们在同一命令中引用了第一个和第二个匹配项。
我们有一个逗号文件(,
),将名字和姓氏分开。我们希望将它们列出为“姓氏,名字”。我们可以用猫
,如下所示,以查看文件中的内容:
猫geeks.txt
像很多 sed
命令,这下一个似乎一开始很难理解:
sed's / ^ \(。* \),\(。* \)$ / \ 2,\ 1 / g'geeks.txt
与我们使用的其他命令一样,这是一个替换命令,搜索模式非常简单。我们将其细分如下:
sed的/
: 普通替换命令。^
: 因为插入符号不在组中([]
),则表示“行的开头”。\(.*\),
: 第一个子表达式是任意数量的任何字符。括在括号中[()
],每个前面都有一个反斜杠(\
),因此我们可以按数字进行引用。到目前为止,我们的整个搜索模式都将转换为从行首到第一个逗号的搜索(,
)表示任意数量的任何字符。\(.*\)
: 下一个子表达式是(再次)任意数量的任何字符。它也被括在括号中[()
],两者都以反斜杠(\
),因此我们可以按数字引用匹配的文本。$/
: 美元符号($
)代表该行的结尾,并将使我们的搜索继续到该行的结尾。我们只是用它来引入美元符号。我们在这里实际上并不需要它,例如星号(*
)将在这种情况下转到该行的末尾。正斜线(/
)完成了搜索模式部分。\ 2,\ 1 / g'
: 因为我们将两个子表达式括在括号中,所以我们可以通过它们的编号来引用它们。因为我们要颠倒顺序,所以我们将它们键入为第二场比赛,第一场比赛
。数字前面必须加一个反斜杠(\
)./G
: 这使我们的命令可以在每行上全局工作。geeks.txt
: 我们正在处理的文件。
您也可以使用Cut命令(C
)替换与您的搜索模式匹配的整行。我们键入以下内容以搜索其中包含单词“ neck”的行,并将其替换为新的文本字符串:
sed'/ neck / c缠住我的手腕'coleridge.txt
现在,我们的新行显示在摘要的底部。
插入行和文本
我们还可以在文件中插入新行和文本。要在任何匹配的行之后插入新行,我们将使用Append命令(一种
).
这是我们要使用的文件:
猫geeks.txt
我们对行进行了编号,以使其更容易理解。
我们键入以下内容以搜索包含单词“ He”的行,并在其下插入新行:
sed'/他/ a->已插入! geeks.txt
我们输入以下内容,并包含“插入命令”(一世
)将新行插入包含匹配文本的行上方:
sed'/ He / i->已插入! geeks.txt
我们可以使用&号(&
)(代表原始匹配文本),以将新文本添加到匹配行。 \1
, \2
,等等,代表匹配的子表达式。
要将文本添加到行的开头,我们将使用匹配该行中所有内容的替换命令,以及将我们的新文本与原始行组合在一起的替换子句。
为此,我们键入以下内容:
sed's /.*/-->插入&/'geeks.txt
我们输入以下内容,包括 G
命令,该命令将在每行之间添加一个空行:
sed'G'geeks.txt
如果要添加两个或多个空行,可以使用 G; G
, G; G; G
, 等等。
删除线
删除命令(d
)删除与搜索模式匹配的行,或用行号或范围指定的行。
例如,要删除第三行,我们将键入以下内容:
sed'3d'geeks.txt
要删除第4至5行的范围,请输入以下内容:
sed'4,5d'geeks.txt
要删除范围之外的行,我们使用感叹号(!
), 如下所示:
sed'6,7!d'geeks.txt
保存更改
到目前为止,我们所有的结果都已打印到终端窗口,但是我们还没有将它们保存在任何地方。要永久保留这些内容,您可以将更改写入原始文件,也可以将其重定向到新文件。
覆盖原始文件需要谨慎。如果你的 sed
该命令是错误的,您可能会对原始文件进行了一些难以撤消的更改。
为了让您高枕无忧 sed
可以在执行命令之前创建原始文件的备份。
您可以使用就地选项(-一世
) 告诉sed
将更改写入原始文件,但是如果您向其添加文件扩展名, sed
会将原始文件备份到新文件。它将具有与原始文件相同的名称,但具有新的文件扩展名。
为了演示,我们将搜索包含“ He”一词的所有行并将其删除。我们还将使用BAK扩展名将原始文件备份到新文件。
为此,我们键入以下内容:
sed -i'.bak''/^.*He.*$/d'geeks.txt
我们输入以下内容以确保我们的备份文件未更改:
猫geeks.txt.bak
我们还可以键入以下命令将输出重定向到新文件并获得类似的结果:
sed -i'.bak''/^.*He.*$/d'geeks.txt> new_geeks.txt
我们用 猫
确认更改已写入新文件,如下所示:
猫new_geeks.txt
唱完了所有这些
您可能已经注意到,即使这份快速入门 sed
很长该命令有很多功能,甚至可以做更多的事情。
希望这些基本概念提供了坚实的基础,您可以在不断学习的基础上继续构建。