使用AWK或Perl进行转置

使用AWK或Perl进行转置,perl,unix,awk,Perl,Unix,Awk,您好,我想使用AWK或Perl获得以下格式的输出文件。我的输入文件是一个空格分隔的文本文件。这类似于我前面的一个问题,但在本例中,输入和输出没有格式。我的列位置可能会改变,所以我希望使用一种不参考列号的技术 输入文件 id quantity colour shape size colour shape size colour shape size 1 10 blue square 10 red triangle 12 pink circle 20 2 12 yellow pentagon 3 o

您好,我想使用AWK或Perl获得以下格式的输出文件。我的输入文件是一个空格分隔的文本文件。这类似于我前面的一个问题,但在本例中,输入和输出没有格式。我的列位置可能会改变,所以我希望使用一种不参考列号的技术

输入文件

id quantity colour shape size colour shape size colour shape size
1 10 blue square 10 red triangle 12 pink circle 20
2 12 yellow pentagon 3 orange rectangle 4 purple oval 6
期望输出

id colour shape size
1 blue square 10
1 red triangle 12
1 pink circle 20
2 yellow pentagon 3
2 orange rectangle 4
2 purple oval 6
我正在使用丹尼斯·威廉姆森的代码。唯一的问题是,我得到的输出在转置字段中没有空间分隔。我需要一个间隔

#!/usr/bin/awk -f
BEGIN {
col_list = "quantity colour shape"
# Use a B ("blank") to add spaces in the output before or
# after a format string (e.g. %6dB), but generally use the numeric argument

# columns to be repeated on multiple lines may appear anywhere in
# the input, but they will be output together at the beginning of the line
repeat_fields["id"]
# since these are individually set we won't use B
repeat_fmt["id"] = "%-1s "
# additional fields to repeat on each line

ncols = split(col_list, cols)

for (i = 1; i <= ncols; i++) {
    col_names[cols[i]]
    forms[cols[i]] = "%-1s"
}
}


# save the positions of the columns using the header line
FNR == 1 {
for (i = 1; i <= NF; i++) {
    if ($i in repeat_fields) {
        repeat[++nrepeats] = i
        repeat_look[i] = i
        rformats[i] = repeat_fmt[$i]
    }
    if ($i in col_names) {
        col_nums[++n] = i
        col_look[i] = i
        formats[i] = forms[$i]
    }
}
# print the header line
for (i = 1; i <= nrepeats; i++) {
    f = rformats[repeat[i]]
    sub("d", "s", f)
    gsub("B", " ", f)
    printf f, $repeat[i]
}
for (i = 1; i <= ncols; i++) {
    f = formats[col_nums[i]]
    sub("d", "s", f)
    gsub("B", " ", f)
    printf f, $col_nums[i]
}
printf "\n"
next
}

{
for (i = 1; i <= NF; i++) {
    if (i in repeat_look) {
        f = rformats[i]
        gsub("B", " ", f)
        repeat_out = repeat_out sprintf(f, $i)

    }
    if (i in col_look) {
        f = formats[i]
        gsub("B", " ", f)
        out = out sprintf(f, $i)
        coln++
    }
    if (coln == ncols) {
        print repeat_out out
        out = ""
        coln = 0
    }
}
repeat_out = ""
}
我很抱歉没有包括所有关于实际文件的信息。我这样做只是为了简单,但它并没有捕获我所有的需求

在我的实际文件中,我希望为节点站点子节点转置字段n_cell和n_bsc

NODE SITE CHILD n_cell n_bsc
;
打印(“id颜色形状大小\n”);
而(){
我的@combined_字段=拆分;
my$id=shift(@combined_字段);
while(@combined_字段){
my@fields=($id,拼接(@combined_fields,0,3));
打印(连接(“”,@fields),“\n”);
}
}

您已经告诉我们,您的真实数据由5000多列组成,并且其列位置可能会发生变化,恐怕这还不够

因此,在没有任何适当信息的情况下,我写了这篇文章,它使用标题行来计算数据集的数量和大小,
id
列在哪里,第一个数据集从哪个列开始

它在您的示例数据上运行良好,但我只能猜测它是否会在您的实时文件上运行

use strict;
use warnings;

my @headers = split ' ', <>;

my %headers;
$headers{$_}++ for @headers;

die "Expected exactly one 'id' column" unless $headers{id} // 0 == 1;
my $id_index = 0;
$id_index++ while $headers[$id_index] ne 'id';

my @labels = grep $headers{$_} > 1, keys %headers;
my $set_size = @labels;
my $num_sets = $headers{$labels[0]};

my $start_index = 0;
$start_index++ while $headers[$start_index] ne $labels[0];

my @reformat;

while (<>) {
  my @fields = split;
  next unless @fields;
  my $id = $fields[$id_index];
  for (my $i = $start_index; $i < @fields; $i+=$set_size) {
    push @reformat, [ $id, @fields[$i..$i + $set_size - 1] ];
  }
}

unshift @labels, 'id';
print "@labels\n";
print "@$_\n" for @reformat;

该语言的名称是“Perl”,而不是“Perl”。然而,它是“AWK”。我对这个问题的回答与相同。可能重复我已将上一个标记为删除您的真实文件是什么样子的?您不喜欢这种特定格式的解决方案,而是一点一点地传递信息,就像有5000多列一样。前两列是否总是
id
quantity
?其余的列是否总是
颜色
形状
大小
?信息是否总是以三列为一组?还有什么我们应该知道的吗?
perl script.pl infle>outfile
或in-place:
perl-i script.pl文件
我的实际输入文件有超过5k列,因此希望使用标题行而不是列引用固定列和列进行转置ids@Santosh皮莱,他们总是按同样的顺序吗?如果是的话,了解列数会更有用。然后将
3
更改为我代码中的那个数字。如果它们的顺序不总是相同的,你怎么知道哪一列属于哪一行?
<>;
print("id colour shape size\n");

while (<>) {
   my @combined_fields = split;
   my $id = shift(@combined_fields);
   while (@combined_fields) {
       my @fields = ( $id, splice(@combined_fields, 0, 3) );
       print(join(' ', @fields), "\n");
   }
}
use strict;
use warnings;

my @headers = split ' ', <>;

my %headers;
$headers{$_}++ for @headers;

die "Expected exactly one 'id' column" unless $headers{id} // 0 == 1;
my $id_index = 0;
$id_index++ while $headers[$id_index] ne 'id';

my @labels = grep $headers{$_} > 1, keys %headers;
my $set_size = @labels;
my $num_sets = $headers{$labels[0]};

my $start_index = 0;
$start_index++ while $headers[$start_index] ne $labels[0];

my @reformat;

while (<>) {
  my @fields = split;
  next unless @fields;
  my $id = $fields[$id_index];
  for (my $i = $start_index; $i < @fields; $i+=$set_size) {
    push @reformat, [ $id, @fields[$i..$i + $set_size - 1] ];
  }
}

unshift @labels, 'id';
print "@labels\n";
print "@$_\n" for @reformat;
id colour shape size
1 blue square 10
1 red triangle 12
1 pink circle 20
2 yellow pentagon 3
2 orange rectangle 4
2 purple oval 6