从字符串中删除文本
1. 概述
在各种情况下,我们可能希望删除特定字符或一组字符之后的文本。例如,一个典型的场景是当我们想要删除特定文件名的扩展名时。
在这个快速教程中,我们将探索几种方法来了解如何操作字符串以删除给定模式后的文本。我们将在示例中使用Bash shell,但这些命令也可以在其他 POSIX shell 中使用。
2. 原生字符串操作
让我们首先看看如何使用Bash 提供的一些内置字符串操作 操作来删除文本。为此,**我们将使用 shell 的一项称为参数扩展 **的功能。
快速回顾一下,参数扩展是 Bash 扩展具有给定值的变量的过程。为了实现这一点,我们只需使用一个美元符号,后跟我们的变量名,用大括号括 起来:
my_var="Hola Mundo"
echo ${my_var}
正如预期的那样,上面的示例导致输出:
Hola Mundo
但正如我们将在扩展过程中看到的那样,我们也可以修改变量值或将其替换为其他值。
现在我们了解了参数扩展的基础知识,在接下来的小节中,我们将解释如何删除部分变量的几种不同方法。
在我们所有的示例中,我们将专注于一个非常简单的用例来删除文件名的文件扩展名。
2.1. 使用给定的位置和长度提取字符
我们将首先了解如何使用给定的起始位置提取特定长度的子字符串:
my_filename="interesting-text-file.txt"
echo ${my_filename:0:21}
这给了我们输出:
interesting-text-file
在此示例中,我们从my_filename变量中提取字符串。从位置 0 开始,长度为 21 个字符。实际上,我们说的是删除位置 21 之后的所有文本,在这种情况下是 .txt 扩展名。
尽管此解决方案有效,但仍有一些明显的缺点:
- 并非所有文件名都具有相同的长度
- 我们需要计算文件扩展名开始的位置,以使其成为更动态的解决方案
- 肉眼看来,代码实际上在做什么并不是很直观
在下一个示例中,我们将看到一个更优雅的解决方案。
2.2. 删除最短匹配
现在我们将看看如何从变量后面删除最短的子字符串匹配:
echo ${my_filename%.*}
让我们更详细地解释一下我们在上面的示例中所做的事情:
我们再次删除子字符串 ‘.txt’ 导致输出:
interesting-text-file
2.3. 删除最长的匹配
同样,我们也可以从文件名中删除最长的子字符串匹配。现在让我们假设我们有一个稍微复杂一点的场景,其中我们的文件名有多个扩展名:
complicated_filename="hello-world.tar.gz"
echo ${complicated_filename%%.*}
在这个变体中,’%%.*’ 从complex_filename变量的后面去除了 ‘.*’ 的最长匹配。这只是匹配“.tar.gz”导致:
hello-world
值得一提的是,Bash 最短匹配和最长匹配都不支持正则表达式。所以,我们需要使用 glob。
2.4. 使用查找和替换
在最后一个字符串操作示例中,我们将看到如何使用 Bash 的内置查找和替换功能:
echo ${my_filename/.*/}
为了理解这个例子,我们先来了解一下子串替换的语法:
${string/substring/replacement}
现在把它放到上下文中,我们将替换my_filename变量中 ‘.*’ 的第一个匹配项,并将其替换为空字符串。在这种情况下,我们再次删除扩展。
3. 使用sed命令
在倒数第二部分,我们将了解如何使用*sed *命令。sed命令是一个强大的流编辑器,我们可以使用它来执行基本和复杂的文本转换。
使用此命令,我们可以找到一个模式并将其替换为另一个模式。当替换占位符为空时,模式被删除。
根据我们的另一个示例,我们将简单地将输入字符串提供给 sed命令:
$ sed 's/[.].*//' <<< 'hello-world.tar.gz'
hello-world
在此示例中,sed命令搜索第一次出现的 ’ 。’ 字符并删除它和它之后的所有字符。
模式“ [.].* ”是一个正则表达式。正则表达式中的单个点具有特殊含义:匹配任何字符。例如,*“.*”*表示任何字符序列。
因此,如果我们想匹配一个文字点字符,我们需要转义点“\”。或使用字符类“[.]”。
4. 使用cut命令
在最后一个示例中,我们将探索cut 命令。顾名思义,我们可以使用cut命令从文本中删除字段。
回到我们的问题,无论X在文本中出现多少次,第一个字段始终是答案:
$ cut -f1 -d"." <<< 'hello-world.tar.gz'
hello-world
让我们更详细地看一下该命令以正确理解它:
- 我们首先使用*-f*选项指定字段编号,该字段编号指示要提取的字段
- -d选项用于指定字段分隔符或定界符,在本例中为“.” 。
输出字段由一次出现的字段分隔符分隔。这意味着在我们的示例中,我们最终得到三个由点分隔的字段。因此,我们选择第一个并在此过程中丢弃其余文本。