【问题标题】:Use grep command to find a word and then print the entire column in perl script使用 grep 命令查找一个单词,然后在 perl 脚本中打印整个列
【发布时间】:2016-07-16 14:40:51
【问题描述】:

我有一个 .csv 文件,我想在其中查找特定单词“ELECTRICIANS”,它是该列中的第一个条目。我想打印名称为 ELECTRICIANS 的整个列,如果我 grep 任何其他单词,应该打印一个错误。

我已经进行了grep操作如下:

my $exit = system("grep -q $column_name $file_name");
if ($exit == 0)
{
        print "Entered column name $column_name found in file $file_name\n";
}
else {
        print "Column name not found, try again!\n";
        exit;
}

现在如何打印“ELECTRICIANS”下文件中的列?

.csv文件内容如下:

WEEK,SITE ENGINEERS,SITE ENGINEERS 2,ELECTRICIANS,ELECTRICIANS 2
ONE,13,28,17,29   
TWO,13,30,18,27 
THREE,13,30,14,23  
FOUR,15,30,12,29 
FIVE,15,22,16,24  
SIX,16,30,20,30 
SEVEN,12,27,13,29  
EIGHT,19,22,16,29 
NINE,19,21,19,30  
TEN,12,22,14,30,13

【问题讨论】:

  • 在您的方法中,您必须将 grep 命令的结果存储在 Perl 变量中。这意味着您不能使用system("grep..."),而是使用qx(grep....) 之类的东西。但是为什么你创建一个子进程只是为了 grepping 行?您可以完全在 Perl 中轻松完成此操作。
  • 我不知道 qx 语法。如何将 grep 命令的输出保存到变量中?
  • my $output = qx(...)。请参阅 perlop 联机帮助页。
  • 我已经修复了您的 csv 文件示例的格式。如果我弄错了,请自行编辑。

标签: perl scripting grep


【解决方案1】:

您的示例数据的最后一行似乎有一个额外的列。

但这就是你想要的。

#!/usr/bin/perl

use strict;
use warnings;
use 5.010;

# read header
my @cols = split /,/, <DATA>;

# Process the rest of the data
while (<DATA>) {
  my %data;
  @data{@cols} = split /,/;
  say $data{ELECTRICIANS};
}

__DATA__
WEEK,SITE ENGINEERS,SITE ENGINEERS 2,ELECTRICIANS,ELECTRICIANS 2
ONE,13,28,17,29
TWO,13,30,18,27
THREE,13,30,14,23
FOUR,15,30,12,29
FIVE,15,22,16,24
SIX,16,30,20,30
SEVEN,12,27,13,29
EIGHT,19,22,16,29
NINE,19,21,19,30
TEN,12,22,14,30,13

【讨论】:

    【解决方案2】:

    你正在编写一个 Perl 脚本,没有必要在 shell 中生成一个子进程来调用其他 shell 函数。 Perl 内置了 grep。下面作为示例演示如何完全在 Perl 中实现相同的结果。我还包括了 cmets 来解释脚本。

    use strict;
    use warnings;
    
    #set the column name, this could be changed to accept input from user, 
    #also read from the data file handle, this could also be changed to read from any other file
    my $column = "ELECTRICIANS";
    my @headers = split(',',<DATA>);
    
    #Check for the column name rom the headers just read from the file handle, if not found then exit
    unless (grep {$_ eq "$column"} @headers){
        print "Column name $column not found, try again!\n";
        exit 1;
    }
    
    print $column, "\n";
    
    #if we got to hear then the CSV file must have the column we are insterested in so start looping though the lines
    #split each line into fields then for each lin make a hash using the headers and the fields. then we can print the column
    #we are interested in
    while(<DATA>){
        chomp();
        my @fields = split(',');
        my %data;
        @data{@headers}=@fields;
        print $data{$column}, "\n";
    }
    
    __DATA__
    WEEK,SITE ENGINEERS,SITE ENGINEERS 2,ELECTRICIANS,ELECTRICIANS 2 
    ONE,13,28,17,29 
    TWO,13,30,18,27 
    THREE,13,30,14,23 
    FOUR,15,30,12,29 
    FIVE,15,22,16,24 
    SIX,16,30,20,30 
    SEVEN,12,27,13,29 
    EIGHT,19,22,16,29 
    NINE,19,21,19,30 
    TEN,12,22,14,30,13
    

    这会产生输出

    ELECTRICIANS
    17
    18
    14
    12
    16
    20
    13
    16
    19
    14
    

    在读取每一行并将其放入散列时,您还可以打印其他列,因为您知道每个字段的列名。

    【讨论】:

      【解决方案3】:

      我经常因为我的单行而受到批评,但这里有一个:

      perl -F, -slane '
          if ($. == 1) {
              for ($i=0; $i<@F; $i++) {
                  if ($F[$i] eq $colname) {
                      $colno = $i;
                      last;
                  }
              }
              die "cannot find $colname column" unless defined $colno;
          }
          print $F[$colno]
      ' -- -colname=ELECTRICIANS file.csv
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-06-26
        • 2023-03-21
        • 2019-04-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-12-08
        相关资源
        最近更新 更多