如何在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

注意之间的逗号 14。这 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; GG; 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 很长该命令有很多功能,甚至可以做更多的事情。

希望这些基本概念提供了坚实的基础,您可以在不断学习的基础上继续构建。


$config[zx-auto] not found$config[zx-overlay] not found