如何在Bash中解析CSV文件


CSV文件是一种我们在互联网上广泛使用的常见文件格式。它们基本上是一种由行组成的文件类型,每一行都被视为一个简单的表格中的行。顾名思义,CSV(逗号分隔值)意味着每一行中的数据都由逗号分隔。

CSV文件只是纯文本,我们可以在任何编辑器中查看和编辑它们。我们使用这种类型的文件常见的字段包括电子表格、数据库、存储配置数据以及API之间的数据交换。

在Linux中,有很多方法可以解析这样的文件。在本教程中,我们将介绍使用Bash脚本解析CSV文件的不同方法。

CSV文件示例

为了了解如何处理CSV文件,我们首先需要了解这些文件中的数据是如何组织的。

假设我们有一个名为example.csv的文件,其内容如下:

Name,Age,City
John Doe,28,New York
Jane Smith,34,Los Angeles
Sam Johnson,25,Chicago
Emily Davis,40,Houston

正如你所看到的,我们有几行,每一行都使用逗号来分隔数据。你的文件可能很长且很复杂,但结构保持不变。

使用cut命令

cut命令可以用于任何类型的文本文件,而不仅仅是CSV文件。在我们的例子中,我们可以用它来解析CSV文件。如果你正在寻找文件内的特定数据,cut命令非常有用。

cut命令的语法很简单。我们传递命令名称,然后是-d选项来指定我们需要使用的分隔符(在我们的例子中,它将是一个逗号),然后是-f选项来指定我们正在处理的列号。

Bash中cut命令的示例

以下是Bash中使用cut命令的一些示例:

示例1:从全名中获取名字

在示例文件中,姓名位于第一列,最后提供的是我们的文件名:

cut -d "," -f 1 example.csv

如果我们运行这个命令,应该会得到这样的输出

Name
John Doe
Jane Smith
Sam Johnson
Emily Davis

我们得到了命令选项中指定的第1列。在你的情况下,这可能会有所不同,具体取决于你正在处理的文件,因此请根据需要调整命令。

一旦我们得到第一列,我们需要更具体地只获取名字。为此,我们可以再次使用cut命令,但这次我们将使用空格作为分隔符,因为如果你注意的话,全名在名字和姓氏之间有一个空格(John Doe)。

此命令的语法如下:

cut -d "," -f 1 example.csv | cut -d " " -f 1

我们使用管道(|)将显示全名的第一个输出传递给另一个cut命令,该命令将获取第一列,分隔符是空格(" ")。如果你的分隔符不是空格,请相应地调整它。

如果我们运行这个命令,我们应该得到想要的结果:

Name
John
Jane
Sam
Emily

示例2:从名字中获取第一个字符

cut命令的功能不止于此。我们可以使用字符而不是常规分隔符来分割和过滤结果。

例如,假设我们需要获取名字中的第一个字符。我们该怎么做呢?我们可以使用另一个选项-c,它处理字符,如下所示:

cut -d "," -f 1 example.csv | cut -d " " -f 1 | cut -c 1

这将给我们这样的输出

N
J
J
S
E

我们第三次使用了cut,并将值1传递给-c选项,以获取名称中的第一个字符。

示例3:获取除第一个字符以外的其余名称

如果我们需要获取除第一个字符以外的其余名称呢?我们可以这样做:

cut -d "," -f 1 example.csv | cut -d " " -f 1 | cut -c 2-

在这里,我们从第二个字符开始,使用(-)获取单词的其余部分。输出将是:

ame
ohn
ane
am
mily

你可以根据需要对输出做任何你想做的事情——将其保存到文件、对其进行排序或将其传递给另一个命令。

再举一个例子来演示cut命令的功能:在前面的例子中,我们只提取了一列。但是,如果你想提取多列,你可以使用-f选项,如下所示:

cut -d "," -f 1,2 example.csv

这将给我们第一列和第二列。请记住,我们的示例文件有三列。输出将是:

Name,Age
John Doe,28
Jane Smith,34
Sam Johnson,25
Emily Davis,40

如果你想获取例如第一列和第三列,你可以像这样调整命令:

cut -d "," -f 1,3 example.csv

使用自定义Shell脚本

我们可以根据需要解析和格式化输出的另一种方法是使用自定义shell脚本

在Bash脚本中,我们有很多方法可以进行解析。我们可以使用cut,就像我们在前面的例子中看到的那样,或者使用awk,或者我们可以使用简单的循环逐行读取文件。

在与CSV文件相同的目录下,创建一个Bash文件(例如,parse.sh)并用以下代码填充它:

#!/bin/bash

IFS=","

while read -r col1 col2 col3
do
   echo "Person Name: $col1"
   echo "Person Age : $col2"
   echo "City       : $col3"
done < example.csv

让我们理解这段代码的作用:

  • #!/bin/bash − 这告诉shell这个文件是一个Bash脚本。
  • IFS="," − 这代表内部字段分隔符,用于分隔字段的字符(在本例中为逗号)。
  • while read -r col1 col2 col3 − 我们启动一个循环,逐行读取文件并将每个字段的内容存储在一个变量中。在本例中,我们有三个变量,但根据文件内容,可以更多。
  • echo − 用于格式化输出并使其更易读。
  • done < example.csv − 这指定我们想要从中读取的文件。

如果我们运行这个命令,我们应该会得到这样的结果:

Person Name: Name
Person Age : Age
City       : City
Person Name: John Doe
Person Age : 28
City       : New York
Person Name: Jane Smith
Person Age : 34
City       : Los Angeles
Person Name: Sam Johnson
Person Age : 25
City       : Chicago
Person Name: Emily Davis
Person Age : 40
City       : Houston

因为我们逐行读取文件,我们也得到了第一行(Name, Age, City),这不是我们需要的。我们如何忽略这一行呢?

我们可以这样做:

#!/bin/bash

IFS=","
((first = -1))

while read -r col1 col2 col3
do
   ((first++)) 
   if [ "$first" = 0 ]; then    
      continue         
   fi
   echo "Person Name: $col1"
   echo "Person Age : $col2"
   echo "City       : $col3"
done < example.csv

我们添加了一个名为first的变量,其值为-1。在循环中,我们递增变量((first++))并检查变量是否等于0。如果是,我们跳过该行并从下一行开始。

结果,我们应该得到:

Person Name: John Doe
Person Age : 28
City       : New York
Person Name: Jane Smith
Person Age : 34
City       : Los Angeles
Person Name: Sam Johnson
Person Age : 25
City       : Chicago
Person Name: Emily Davis
Person Age : 40
City       : Houston

Bash脚本是一种功能强大的语言,拥有许多我们可以用来完成几乎所有需要完成的任务的工具。这只是一個例子;你可以根据需要进行调整。

结论

在本教程中,我们解释了在Bash中解析CSV文件的一些方法。我们从cut实用程序开始,它具有许多功能并且易于使用。然后,我们使用了一个自定义Bash脚本,它遍历文件并逐行读取它,我们可以根据文件和我们的需要进行调整。

更新于:2024年11月4日

28 次浏览

开启你的职业生涯

完成课程获得认证

开始学习
广告