📜  珀尔 |读取 CSV 文件

📅  最后修改于: 2022-05-13 01:55:08.821000             🧑  作者: Mango

珀尔 |读取 CSV 文件

Perl 最初是为文本处理而开发的,例如从指定的文本文件中提取所需的信息并将文本文件转换为不同的形式。读取文本文件是 Perl 中非常常见的任务。例如,您经常会阅读 CSV(逗号分隔值)文件来提取数据和信息。

可以使用任何文本编辑器(例如notepadnotepad++等)创建 CSV 文件。将内容添加到记事本中的文本文件后,将其存储为使用.csv扩展名的 csv 文件。

CSV 文件示例:

Store the above file as new.csv

CSV 文件可用于管理企业或公司数据库的记录文件。这些文件可以在 Excel 中轻松打开,并且可以使用任何合适的软件进行操作。 Perl 还通过从文件中提取值、操作这些值并将它们恢复到文件中来支持这些“csv”文件的操作和创建。为了从特定行中提取每个值,我们将使用split函数。

使用 Split() 进行数据提取

split() 是 Perl 中的一个预定义函数,用于在分隔符的帮助下将字符串分成几部分。这个分隔符可以根据用户的要求是任意字符,但一般我们以逗号作为分隔符。
split()有两个参数。第一个是分隔符,第二个是需要拆分的字符串。

例子:

Input: $s = "Johny loves Sugar" 
Output: "Johny", "loves", "Sugar"
If Input string is passed to split function as,
@words = split("", $s);
The array @words will be filled with 3 values: “Johny”, “loves” and “Sugar”.

笔记:

If $words[2] is printed then result will be "Sugar" as array indexing starts from 0.

按照以下步骤使用分隔符将 CSV 文件的行拆分为多个部分:
第一步:逐行读入文件。
第 2 步:对于每一行,将所有值存储在一个数组中。
第三步:将所有值一一打印出来得到结果

让我们举一个例子来更好地理解这个主题。以下是split()函数的代码,用于使用分隔符分隔存储在 new.csv 文件中的字符串:

Perl
use strict;
   
my $file = $ARGV[0] or die;
open(my $data, '<', $file) or die;
   
while (my $line = <$data>) 
{
    chomp $line;
   
    # Split the line and store it
    # inside the words array
    my @words = split ", ", $line;  
   
    for (my $i = 0; $i <= 2; $i++)
    {
        print "$words[$i] ";
    }
    print "\n";
}


Perl
use strict;
   
# Using Text::CSV file to allow
# full CSV Reader and Writer
use Text::CSV;
   
my $csv = Text::CSV->new({ sep_char => ', ' });
    
my $file_to_be_read = $ARGV[0] or die;
   
# Reading the file
open(my $data_file, '<', $file_to_be_read) or die;
while (my $line = <$data_file>) 
{
  chomp $line;
    
  # Parsing the line
  if ($csv->parse($line)) 
  {
         
      # Extracting elements
      my @words = $csv->fields();
      for (my $i = 0; $i <= 2; $i++) 
      {
          print "$words[$i] ";
      }
   
      print "\n";
  } 
  else
  {
      # Warning to be displayed
      warn "Line could not be parsed: $line\n";
  }
}


Perl
use strict;
   
# Using Text::CSV file to allow
# full CSV Reader and Writer
use Text::CSV;
   
my $file = $ARGV[0] or die;
   
my $csv = Text::CSV->new (
{
    binary => 1,
    auto_diag => 1,
    sep_char => ', '
});
   
my $sum = 0;
   
# Reading the file
open(my $data, '<:encoding(utf8)', $file) or die;
   
while (my $words = $csv->getline($data)) 
{
    for (my $i = 0; $i < 3; $i++) 
    {
        print "$words->[$i]";
    }
    print "\n";
}
   
# Checking for End-of-file
if (not $csv->eof) 
{
    $csv->error_diag();
}
close $data;


将上述代码保存在扩展名为.pl的文本文件中。在这里,我们将它保存为test.pl

使用以下命令执行上述保存的文件:

perl test.pl new.csv

输出:

转义逗号字符

有时,可能有一个文件在字符串的字段中包含逗号,如果将其删除,则会改变数据的含义或使记录变得无用。在这种情况下,如果使用split()函数,即使在引号内,它也会在每次获取逗号作为分隔符时将值分开,因为split()函数不关心引号,也不理解关于 CSV 的任何信息。它只是剪切找到分隔字符的位置。

以下是 CSV 文件,引号内有逗号:

在上面的 CSV 文件中,可以看到第一个字段本身有一个逗号,因此用引号括起来。但是如果我们在这个文件上运行split()函数,那么它就不会关心任何这样的引号。以下是对此类文件应用split()函数的结果:

在上面的文件中, split()函数将字符串字段分成几部分,即使它在引号内,也因为我们在代码中只打印了三个字段,因此,最后一个字符串的第三个字段被丢弃在输出文件中.

为了处理这种情况,Perl 中添加了一些限制和范围,这些限制允许编译器跳过引号内的字段划分。
我们使用允许完整的 CSV 读取器和写入器的TEXT::CSV 。 TEXT::CSV 是 Perl 中 MCPAN 的一个模块,它允许许多新功能,例如读取、解析和写入 CSV 文件。可以使用以下编译指示将这些模块包含在 Perl 程序中:

use Text::CSV

但首先,需要在您的设备上下载并安装此模块才能使用其功能。

安装 TEXT::CSV :
对于 Windows:

perl -MCPAN -e shell
install Text::CSV

对于基于 Debian/Ubuntu 的系统:

$ sudo apt-get install libtext-csv-perl

对于基于 RedHat/Centos/Fedora 的系统:

$ sudo yum install perl-Text-CSV

以下是在我们的 new.csv 文件上运行的代码,用于转义引号内的逗号字符:

Perl

use strict;
   
# Using Text::CSV file to allow
# full CSV Reader and Writer
use Text::CSV;
   
my $csv = Text::CSV->new({ sep_char => ', ' });
    
my $file_to_be_read = $ARGV[0] or die;
   
# Reading the file
open(my $data_file, '<', $file_to_be_read) or die;
while (my $line = <$data_file>) 
{
  chomp $line;
    
  # Parsing the line
  if ($csv->parse($line)) 
  {
         
      # Extracting elements
      my @words = $csv->fields();
      for (my $i = 0; $i <= 2; $i++) 
      {
          print "$words[$i] ";
      }
   
      print "\n";
  } 
  else
  {
      # Warning to be displayed
      warn "Line could not be parsed: $line\n";
  }
}

输出:

在上面的例子中,可以看到第一个字段现在有一个逗号,它在解析 CSV 文件时已被转义。

my $csv = Text::CSV->new({ sep_char => ', ' }); 

用“,”隔开。
上一行描述了在类上调用构造函数的方式。使用箭头->完成构造函数调用。

$csv->parse($line)

此调用将尝试解析当前行并将其拆分为多个部分。根据成功或失败返回真或假。

带有嵌入换行符的字段

在 CSV 文件中,也可能有一些字段是多行的,或者在单词之间嵌入了新行。与没有嵌入新行的其他文件相比,这些类型的多行字段通过split()函数时的工作方式非常不同。
例子:

Perl 提供了一个getline()方法来处理这类文件。

Perl

use strict;
   
# Using Text::CSV file to allow
# full CSV Reader and Writer
use Text::CSV;
   
my $file = $ARGV[0] or die;
   
my $csv = Text::CSV->new (
{
    binary => 1,
    auto_diag => 1,
    sep_char => ', '
});
   
my $sum = 0;
   
# Reading the file
open(my $data, '<:encoding(utf8)', $file) or die;
   
while (my $words = $csv->getline($data)) 
{
    for (my $i = 0; $i < 3; $i++) 
    {
        print "$words->[$i]";
    }
    print "\n";
}
   
# Checking for End-of-file
if (not $csv->eof) 
{
    $csv->error_diag();
}
close $data;

输出:

在上面的 CSV 文件中,嵌入的换行符现在使用getline()方法处理,Perl 根据程序员的要求将新字段视为一个字段,因此放在引号内。