使用perl解析文件并将特定值插入数据库

时间:2010-04-22 16:02:07

标签: perl sed

免责声明:我是perl脚本编写的新手,这部分是一个学习练习(但仍然是一个工作项目)。另外,我对shell脚本有了更强的把握,所以我的例子可能会以这种思维方式进行格式化(但我想在perl中创建它们)。提前抱歉我的详细程度,我想确保我至少清楚地明白我的观点

我有一个文本文件(参考指南),它是一个转换为文本的Word文档,然后在Notepad ++中从Windows换成UNIX格式。该文件是统一的,因为该文件的每个部分都具有相同的字段/格式/表。

我计划做的事情,基本的方法是获取每个部分,用唯一的批处理作业名称键入并将所有值放入数据库(或者只是一个excel文件),以便可以搜索所有字段/为每个作业编辑比在word文件中更容易编辑,并可能在以后创建一个Web界面。

所以我想做的是通过做类似的事情来抓住每个部分:
sed -n '/job_name_1_regex/,/job_name_2_regex/' file.txt - 如何在perl脚本中格式化?
(总共抓住那个部分,然后从那里进一步分解)

要在脚本中读取文件,我有open FORMAT_FILE, 'test_format.txt';,然后使用foreach $line (<FORMAT_FILE>)逐行解析文件。 - 有更好的方法吗?

我的下一个问题是,因为我从带有表格的单词doc转换而来,看起来像:

 Table Heading 1      Table Heading 2
Heading 1/Value 1    Heading 2/Value 1
Heading 1/Value 2    Heading 2/Value 2

但文本文件如下:

Table Heading 1 
Table Heading 2
Heading 1/Value 1
Heading 1/Value 2
Heading 2/Value 1
Heading 2/Value 2

所以我希望将“标题1”和“标题2”作为列名称,然后将各自的值放在那里。我只是不确定如何从文本文件中获取与标题相关的值。标题1的值将始终是标题1加2的行号(标题1,标题2,标题1的值)。我知道这可以很容易地在awk / sed中完成,只是不确定如何解决它里面的 perl脚本。

--- --- EDIT
为此,我想做一个类似的数组:

my @heading1 = ($value1, $value2, etc.)
my @heading2 = ($value1, $value2, etc.)

我只需要能够将正确的值和标题关联在一起。因此,heading1 = 在heading2 之后的行(其中值开始)。 就像说(在shell中):

x=$(grep -n "Heading 1" file.txt | cut -d":" -f1) #gets the line that "Heading 1" is on in the file
(( x = x+2 )) #adds 2 to the line (where the values will start)
#print values from file.txt from the line where they start to the
#last one (I'll figure that out at some point before this)
sed -n "$x,$last_line_of_values p" file.txt

目前这是一起超级黑客攻击,试图详细说明我想要做的事情......让我知道它是否清除了一点...... --- / EDIT ---

在拥有所有正确的值之后,将它链接到数据库也可能是一个问题,我还没有开始研究perl与DB交互的方式。

很抱歉,如果这有点散乱......我的脑子里还没有完全形成。

2 个答案:

答案 0 :(得分:3)

http://perlmeme.org/tutorials/connect_to_db.html

#!/usr/bin/perl
use strict;
use warnings;
use DBI;

my $driver = "mysql";   # Database driver type
my $database = "test";  # Database name
my $user = "";          # Database user name
my $password = "";      # Database user password

my $dbh = DBI->connect(
    "DBI:$driver:$database",
    $user, $password,
    {
        RaiseError => 1,
        PrintError => 1,
    }
) or die $DBI::errstr;

my $sth = $dbh->prepare("
        INSERT INTO test 
                    (col1, col2)
             VALUES (?, ?)
    ") or die $dbh->errstr;

my $intable = 0;
open my $file, "file.txt" or die "can't open file $!";
while (<$file>)  {
  if (/job_name_1_regex/../job_name_2_regex/) { # job 1 section
    $intable = 1 if /Table Heading 1/; # table start
    if ($intable) {
      my $next_line = <$file>; # heading 2 line
      chomp; chomp $next_line;
      $sth->execute($_, $next_line) or die $dbh->errstr;
    }
  }
}
close $file or die "can't close file $!";
$dbh->disconnect;

答案 1 :(得分:2)

这篇文章中的几件事......首先,基本的“最佳实践”:

  1. 使用现代的perl。使用

    启动脚本

    use strict; use warnings;

  2. 不使用全局文件句柄,使用词法文件句柄(在变量中声明它们)。

  3. 始终检查“打开”是否有返回值。

    open my $file, "/some/file" or die "can't open file : $!"

  4. 然后,关于模式匹配:我根本不理解你的例子,但我想你想要这样的东西:

    foreach my $line ( <$file> ) {
        if ( $line =~ /regexp1/) { 
        # do something...
        }
    
    }
    

    编辑:关于表,我想最好的事情是构建两个数组,每列一个。 如果我在读取文件时理解正确,则需要拆分行并将一部分放在@ col1数组中,将第二部分放在@col2数组中。简单明了的方法是使用两个临时变量:

    my ( $val1, $val2 ) = split /\s+/, $line;
    push @col1, $val1;
    push @col2, $val2;