首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用Perl合并CSV文件

使用Perl合并CSV文件
EN

Stack Overflow用户
提问于 2015-04-11 08:36:13
回答 2查看 193关注 0票数 0

我有一个CSV文件,我需要使用下面的Perl代码进行合并,但是我无法运行它。它应该输出多个文本文件,但不起作用。

代码语言:javascript
复制
#!/usr/local/bin/perl
#
$template_file_name="rtr-template.txt";
while(<>) {

   ($location, $name, $lo0ip, $frameip, $framedlci, $eth0ip, $x) 
       = split (/,/);

   open(TFILE, "< $template_file_name") || die "config template file $template_file_name: 
$!\n";
   $ofile_name = $name . ".txt";
   open(OFILE, "> $ofile_name") || die "output config file $ofile_name: $!\n";

   while (<TFILE>) {

     s/##location##/$location/;
     s/##rtrname##/$name/;
     s/##eth0-ip##/$eth0ip/;
     s/##loop0-ip##/$lo0ip/;
     s/##frame-ip##/$frameip/;
     s/##frame-DLCI##/$framedlci/;

     printf OFILE $_;
   }
}

CSV文件如下所示

代码语言:javascript
复制
Toronto, Router1, 172.25.15.1, 172.25.16.6,101, 172.25.100.1

这是rtr-template.txt文件

代码语言:javascript
复制
!
version 12.1
service timestamps debug datetime msec
service timestamps log datetime msec
service password-encryption
!
hostname ##rtrname##
!
enable password cisco
enable secret cisco
!
interface Loopback0
 ip address ##loop0-ip## 255.255.255.255
!
interface Serial0/0
 description Frame-Relay Circuit 
 no ip address
 encapsulation frame-relay
 ip route-cache policy
 frame-relay lmi-type ansi
 no shutdown
!
interface Serial0/0.1 point-to-point
 ip address ##frame-ip## 255.255.255.252
 frame-relay interface-dlci ##frame-DLCI##
!
interface FastEthernet0/1
 description User LAN Segment
 ip address ##eth0-ip## 255.255.255.0
 no shutdown
!
router eigrp 99
 network 172.25.0.0
!
snmp-server location ##location##
!
line con 0
 password cisco
 login
 transport input none
line aux 0
 password cisco
 login
line vty 0 4
 password cisco
 login
 transport input telnet
!
end
EN

回答 2

Stack Overflow用户

发布于 2015-04-11 10:30:47

主要的问题是在中双击程序的文件名来运行程序。

<>的工作方式是,它将从命令行中指定的任何文件(出现在@ARGV数组中)读取,或者,如果该数组为空,那么它将从STDIN (通常是键盘)读取。

双击该文件不会给它任何命令行参数,因此它会等待您在出现的黑色窗口中键入输入。这意味着您输入了<RTR-DATA.CSV作为while循环的输入,并且Perl尝试在逗号上拆分它,只给出一个字段,因此它将$location设置为<RTR-DATA.CSV。不是你想要的!

因此,如果您从cmd窗口通过以下方式运行程序

代码语言:javascript
复制
create-configs.pl RTR-DATA.CSV

然后,在程序中,@ARGV将包含RTR-DATA.CSV<>将自动从该文件中读取

下面是关于您的代码的一些进一步说明

  • 在Windows上不需要#!行,它通常将.pl文件扩展名绑定到perl可执行文件
  • 您必须始终将use strictuse warnings放在您编写的每个Perl程序的顶部,并在它们的第一个使用点声明所有变量。这会为你的问题的本质提供一些非常有力的线索
  • 通常,您应该从文件中读取每一行,因为它的末尾有一个换行符,如果您把它放在split返回的最后一个字段的末尾,就会产生问题。
  • 在这种情况下,您可能还应该在正在分割的模式中添加逗号两边的可选空格,以便从它返回的字段中移除前导空格和尾部空格。
  • 您应该始终将词法文件句柄($out_fh而不是OFILE)与三参数形式的open一起使用。

这里是对您的代码的重写,它考虑到了所有这些要点。我希望它能帮上忙

代码语言:javascript
复制
use strict;
use warnings;

my $template_file = 'rtr-template.txt';

while ( <> ) {

    chomp;
    my ($location, $name, $lo0ip, $frameip, $framedlci, $eth0ip) = split /\s*,\s*/;

    open my $t_fh, '<', $template_file
        or die qq{Unable to open "$template_file" for input: $!};

    my $out_file = "$name.txt";
    open my $out_fh, '>', $out_file
        or die qq{Unable to open "$out_file" for output: $!};

    while (<$t_fh>) {

        s/##location##/$location/g;
        s/##rtrname##/$name/g;
        s/##eth0-ip##/$eth0ip/g;
        s/##loop0-ip##/$lo0ip/g;
        s/##frame-ip##/$frameip/g;
        s/##frame-DLCI##/$framedlci/g;

        printf $out_fh $_;
    }
}
票数 1
EN

Stack Overflow用户

发布于 2015-04-12 00:01:06

使用Text::CSV解析CSV文件和Template Toolkit或类似的模板。别再发明轮子了。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/29575833

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档