【问题标题】:capture column and print to file in perl在 perl 中捕获列并打印到文件
【发布时间】:2014-08-19 03:40:24
【问题描述】:

我有一个基本上是组 ID 列表的数组。我将使用数组将 ID 放入使用 foreach 循环的专有 linux 命令中,但也使用数组元素来命名文件(每个 ID 都需要将其输出到自己的单独文件中)。我遇到了一些问题,打开文件并使用 AWK 查找和打印列,或者我也尝试了 split 命令,但我也无法正常工作。以下是我目前所拥有的示例:

#!/usr/bin/perl -w
# Title: groupmem_pull.pl
# Pupose: Pull  group membership from group IDs in array

use strict;
use warnings;

my $gpath = "/home/user/output";
my @grouparray = (
"219",
"226",
"345",
"12",
);
print "Checking Groups:\n";

foreach (@grouparray)
    {
    print `sudo st-admin show-group-config --group $_ | egrep '(Group ID|Group Name)'`;
    print `sudo st-admin show-members --group $_ > "$gpath/$_.txt"`;
    #print `cat $gpath/$_`;
    #print `cat $gpath/$_ | awk -F"|" '{print $2}' >`;
    open (FILE, "$gpath/$_.txt") || die "Can't open file\n: $!";
            while(my $groupid = <FILE>)     {
                                            `awk -F"|" '{print $2}' "$gpath/$_.txt" > "$gpath/$_.txt"`;
                                            #print `cat "$gpath/$_.txt" | awk -F"|" '{print $2}' > $_.txt`;
                                            }

现在它在 AWK 文章上的错误是“在 ./groupmem_pull.pl 第 57 行第 2 行使用未初始化的值 $2 连接 (.) 或字符串”。第一个命令的输出基本上将每个组 ID 拉入一个用管道分隔的文本文件中。我在这个方面玩得很开心,而且我无法让我在 stackoverflow 上找到的一些示例正常工作。感谢您的帮助!

【问题讨论】:

  • 你已经在 Perl 中了,它是 AWK 的超集,那么你为什么不在你的 Perl 代码中做 awk 的东西呢?此外,如果您这样做,则无需编写临时文件...只需直接从 Perl 读取 st-admin 命令输出即可。
  • 嗨,Jim,我对脚本很陌生,所以我的知识有限。您能否通过直接从 Perl 运行 st-admin 命令来扩展您的意思?这不是我已经在做的吗?

标签: arrays perl awk foreach split


【解决方案1】:

我认为 AntonH 对错误消息的看法是正确的。但是,我也认为程序的结果可能不是您所期望的。我也同意,如果消除 AWK 组件,“纯 Perl”解决方案可能会更好。

如果我理解正确,您希望为@grouparray 中的每个组运行此命令。

sudo st-admin show-members --group <group id>

从那里,您读取由竖线字符分隔的第二列,并将该列中的所有值输出到 $gpath 文件夹中名为 &lt;group&gt;.txt 的文件。

如果是这样的话,我认为这样的事情会奏效。

use strict;
use warnings;

my $gpath = "/home/user/output";
my @grouparray = qw(219 226 345 12);

print "Checking Groups:\n";

foreach (@grouparray)
{
   open my $FILE, '-|', qq{sudo st-admin show-members --group $_} or die $!;
   open my $OUT, '>', "$gpath/$_.txt" or die $!;
   while (<$FILE>) {
     # chomp;  # if there are only two fields
     my ($field) = (split /\|/, $_, 3)[1];
     print $OUT $field, "\n";
   }
   close $OUT;
   close $FILE;
}

【讨论】:

  • Hambone,这正是我一开始就应该做的。我不知道你可以 qq{} 一个命令并让它像这样运行它。它的输出与我对每个组的需要完全相同。非常感谢您和大家对此的帮助。
  • 不客气。你可能已经知道了,但是 qq/hello/ 和“你好”是一回事。它只是简化了它,如果你在字符串中有引号,你可以选择几乎任何你想要的边界字符:qq|hello|, qq(hello), qq!hello!
  • 酷,谢谢!现在我只需要弄清楚如何导出为 CSV 而不是 TXT。
  • 使用文本::CSV。它处理 CSV 的所有令人讨厌的细节。
【解决方案2】:

我认为在字符串中不引用 Perl 变量时转义美元可以解决问题(在您的情况下,$2 变为 \$2)。

`awk -F"|" '{print \$2}' "$gpath/$_.txt" > "$gpath/$_.txt"`;

【讨论】:

  • 谢谢安东!这确实让我在没有收到错误消息的情况下继续进行,但是 AWK 命令以某种方式产生了一个空白文件。看看上面 Hambone 的评论 - 现在可能会解决我的空白文件问题。休息一段时间后,我今天要再次尝试剧本。
【解决方案3】:

Hambone 的代码对我有用。 AntonH 也有一个很好的建议,似乎可以解决错误,但它导致输出为空白。最好的方法是通过实施一些 Hambone 的建议来简化我的原始代码,该建议是关于如何调用一个函数,该函数将通过 Split 而不是 AWK 拉出我需要的列。

谢谢!

【讨论】:

    猜你喜欢
    • 2012-01-27
    • 2015-11-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-28
    • 2014-07-22
    • 1970-01-01
    • 2015-01-02
    相关资源
    最近更新 更多