Linux 文件合并

LinuxLinuxBeginner
立即练习

💡 本教程由 AI 辅助翻译自英文原版。如需查看原文,您可以 切换至英文原版

简介

本实验将向你介绍 Linux 中的 join 命令,这是一个强大的实用工具,可让你根据公共字段合并两个文件中的数据。与数据库中的表连接操作类似,此命令在 Linux 环境的数据处理和分析任务中特别有用。

在整个实验过程中,你将学习如何使用带有不同选项的 join 命令来合并不同文件中的数据、处理不同的字段分隔符,并了解 Linux 中文件连接操作的基本原理。当你处理文本文件中的结构化数据时,这些技能将非常有用,这也是系统管理和数据分析中的常见任务。


Skills Graph

%%%%{init: {'theme':'neutral'}}%%%% flowchart RL linux(("Linux")) -.-> linux/BasicFileOperationsGroup(["Basic File Operations"]) linux(("Linux")) -.-> linux/TextProcessingGroup(["Text Processing"]) linux/BasicFileOperationsGroup -.-> linux/cat("File Concatenating") linux/TextProcessingGroup -.-> linux/tr("Character Translating") linux/TextProcessingGroup -.-> linux/join("File Joining") subgraph Lab Skills linux/cat -.-> lab-271313{{"Linux 文件合并"}} linux/tr -.-> lab-271313{{"Linux 文件合并"}} linux/join -.-> lab-271313{{"Linux 文件合并"}} end

理解基本的 join 命令

在这一步中,你将学习 join 命令的基本语法和用法。Linux 中的 join 命令基于公共字段合并两个文件中的行,类似于数据库中的表连接操作。

让我们创建两个示例文件来进行操作。我们将创建包含天气数据的文件,具体是风暴事件的日期及其对应的风向。

首先,创建一个名为 storms.txt 的文件,其中包含风暴 ID 和日期:

echo -e "1:2023-04-01\n2:2023-04-15\n3:2023-05-02" > ~/project/storms.txt

现在,创建另一个名为 winds.txt 的文件,其中包含风暴 ID 和风向:

echo -e "1:NW\n2:SE\n3:NE" > ~/project/winds.txt

让我们查看这些文件的内容,以了解它们的结构:

cat ~/project/storms.txt

你应该会看到以下输出:

1:2023-04-01
2:2023-04-15
3:2023-05-02

现在,让我们查看风向文件:

cat ~/project/winds.txt

你应该会看到以下输出:

1:NW
2:SE
3:NE

注意,两个文件都有一个公共的第一个字段(风暴 ID),可用于连接它们。现在,让我们使用 join 命令基于这个公共字段合并这些文件:

join -t: ~/project/storms.txt ~/project/winds.txt

-t: 选项告诉 join 命令,两个文件中的字段分隔符是冒号 (:)。默认情况下,join 会在每个文件的第一列中查找公共字段。

你应该会看到以下输出:

1:2023-04-01:NW
2:2023-04-15:SE
3:2023-05-02:NE

这个输出显示了两个文件合并后的数据。每行包含:

  • 风暴 ID(公共字段)
  • 日期(来自第一个文件)
  • 风向(来自第二个文件)

join 命令匹配具有相同风暴 ID 的行,并将它们合并为输出中的单行。

连接具有不同字段分隔符的文件

在实际场景中,你经常会遇到使用不同字符作为字段分隔符的文件。这一步将向你展示如何使用 join 命令并结合额外的文本处理来连接此类文件。

让我们创建两个具有不同字段分隔符的文件:

首先,创建一个名为 storms_dash.txt 的文件,其中包含风暴 ID 和日期,使用连字符 (-) 作为分隔符:

echo -e "1-2023-04-10\n2-2023-04-20\n3-2023-05-05" > ~/project/storms_dash.txt

接下来,创建另一个名为 winds_comma.txt 的文件,其中包含风暴 ID 和风向,使用逗号 (,) 作为分隔符:

echo -e "1,NW\n2,SE\n3,NE" > ~/project/winds_comma.txt

让我们查看这些文件的内容:

cat ~/project/storms_dash.txt

你应该会看到:

1-2023-04-10
2-2023-04-20
3-2023-05-05

现在,让我们查看 winds_comma.txt 文件:

cat ~/project/winds_comma.txt

你应该会看到:

1,NW
2,SE
3,NE

这里的挑战在于,join 命令要求两个文件使用相同的字段分隔符。为了解决这个问题,我们需要对其中一个文件进行预处理,使其分隔符与另一个文件匹配。我们可以使用 tr 命令来转换字符:

join -t- ~/project/storms_dash.txt <(tr ',' '-' < ~/project/winds_comma.txt)

此命令执行以下操作:

  1. tr ',' '-' < ~/project/winds_comma.txt - 将 winds_comma.txt 文件内容中的所有逗号转换为连字符
  2. <(...) - 进程替换,将括号内命令的输出视为一个文件
  3. join -t- ~/project/storms_dash.txt - 使用连字符 (-) 作为字段分隔符,将 storms_dash.txt 文件与转换后的数据进行连接

你应该会看到以下输出:

1-2023-04-10-NW
2-2023-04-20-SE
3-2023-05-05-NE

这个输出显示了两个文件连接后的数据,整个过程都使用连字符 (-) 作为字段分隔符。进程替换是 bash 中的一个强大功能,它允许你将命令的输出视为一个文件,而无需创建临时文件。

高级连接选项

在实际的数据处理任务中,你通常需要更高级的连接操作,例如处理未配对的数据或选择特定的字段。这一步将向你介绍 join 命令的这些高级选项。

让我们为示例创建两个更复杂的文件:

echo -e "1:2023-04-01:Thunderstorm\n2:2023-04-15:Hurricane\n3:2023-05-02:Tornado\n4:2023-05-10:Blizzard" > ~/project/storms_types.txt
echo -e "1:High\n2:Medium\n5:Low" > ~/project/severity.txt

让我们查看这些文件的内容:

cat ~/project/storms_types.txt

你应该会看到:

1:2023-04-01:Thunderstorm
2:2023-04-15:Hurricane
3:2023-05-02:Tornado
4:2023-05-10:Blizzard
cat ~/project/severity.txt

你应该会看到:

1:High
2:Medium
5:Low

注意,这些文件的 ID 并不是完全匹配的:

  • severity.txt 中有风暴 ID 5 的条目,但 storms_types.txt 中不存在该 ID
  • storms_types.txt 中有风暴 ID 3 和 4 的条目,但 severity.txt 中不存在这些 ID

默认情况下,join 仅输出两个文件中连接字段匹配的行:

join -t: ~/project/storms_types.txt ~/project/severity.txt

你应该会看到:

1:2023-04-01:Thunderstorm:High
2:2023-04-15:Hurricane:Medium

输出中仅出现了风暴 ID 1 和 2,因为它们是两个文件中都存在的 ID。

处理未配对的行

要在输出中包含未配对的行,你可以使用 -a 选项:

join -t: -a 1 -a 2 ~/project/storms_types.txt ~/project/severity.txt

-a 1 选项告诉 join 包含第一个文件中未配对的行,-a 2 则对第二个文件执行相同的操作。

你应该会看到:

1:2023-04-01:Thunderstorm:High
2:2023-04-15:Hurricane:Medium
3:2023-05-02:Tornado:
4:2023-05-10:Blizzard:
5::Low

注意,未配对的行在对应另一个文件数据的位置有空白字段。

选择特定字段

你还可以使用 -o 选项从每个文件中选择特定的字段包含在输出中:

join -t: -o 1.1,1.3,2.2 ~/project/storms_types.txt ~/project/severity.txt

-o 1.1,1.3,2.2 选项指定了要输出的字段:

  • 1.1:第一个文件的第一个字段(风暴 ID)
  • 1.3:第一个文件的第三个字段(风暴类型)
  • 2.2:第二个文件的第二个字段(严重程度)

你应该会看到:

1:Thunderstorm:High
2:Hurricane:Medium

这个输出仅包含风暴 ID、风暴类型和严重程度级别,省略了日期信息。当处理包含许多字段的文件,但你只需要输出特定字段时,这特别有用。

总结

在本次实验中,你学习了如何在 Linux 系统中使用 join 命令,基于公共字段合并不同文件中的数据。这是在 Linux 环境下进行数据处理和分析的一项必备技能。

你练习了使用带有各种选项的 join 命令:

  • 使用相同字段分隔符连接文件的基本语法
  • 使用进程替换和 tr 命令处理具有不同字段分隔符的文件
  • 使用 -a 选项在输出中包含未配对的行
  • 使用 -o 选项从每个文件中选择特定字段进行输出

join 命令在处理结构化文本数据、日志文件,或者在任何需要基于公共标识符合并不同来源信息的场景中特别有用。这项技能与其他 Linux 文本处理命令(如 grepsedawk)相辅相成,为你提供了一个强大的命令行数据操作工具集。