Perl 有条件地用列名替换单元格值

Perl 有条件地用列名替换单元格值,perl,sed,awk,Perl,Sed,Awk,我有一个165 x 165的秩矩阵,这样每一行的值都在1-165之间。我想解析每一行并删除所有>=5的值,按递增顺序对每一行进行排序,然后用原始矩阵中的列名称替换值1-5 例如,对于k行,值1、2、3、4、5将在前两次转换后产生,并将被p、d、m、n、a替换。我假设您的数组由数组组成 Awk、Sed或Perl都没有多维数组。但是,可以使用数组的数组在Perl中模拟它们 $a[0]->[0] = xx; $a[0]->[1] = yy; [...] $a[0]->[164] =

我有一个165 x 165的秩矩阵,这样每一行的值都在1-165之间。我想解析每一行并删除所有>=5的值,按递增顺序对每一行进行排序,然后用原始矩阵中的列名称替换值1-5


例如,对于k行,值1、2、3、4、5将在前两次转换后产生,并将被p、d、m、n、a替换。

我假设您的数组由数组组成

Awk、Sed或Perl都没有多维数组。但是,可以使用数组的数组在Perl中模拟它们

$a[0]->[0] = xx;
$a[0]->[1] = yy;
[...]
$a[0]->[164] = zz;

$a[1]->[0] = qq;
$a[1]->[1] = rr;
[...]
$a[164]->[164] = vv;
这有意义吗

我正在调用行
$x
和列
$y
,因此数组中的元素将是
$array[$x]->[$y]
。那好吗

for my $x (1..164) { #First row is column names
  for my $y (0..164)  {
    if ($array[$x]->[$y] <= 5) {
        $array[$x]->[$y] = $array[0]->[$y];
    }
  }
}
好的,您的列名将在
$array[0]
行中,因此如果我们在
$array[$x]->[$y]
中找到小于5的值,我们知道列名在
$array[0]->[$y]
中。那好吗

for my $x (1..164) { #First row is column names
  for my $y (0..164)  {
    if ($array[$x]->[$y] <= 5) {
        $array[$x]->[$y] = $array[0]->[$y];
    }
  }
}
对于我的$x(1..164){#第一行是列名
我的$y(0..164){
如果($array[$x]->[$y][$y]=$array[0]->[$y];
}
}
}
我只是检查所有的行,对于每一行,所有的列,并检查值。如果值小于或等于5,我用列名替换它


我希望我不是在为你做功课。

这个GNU-sed解决方案可能会工作,但它需要放大,因为我只使用10x10矩阵进行测试:

# { echo {a..j};for x in {1..10};do seq 1 10 | shuf |sed 'N;N;N;N;N;N;N;N;N;s/\n/ /g';done; }> test_data
# cat test_data                                                                                 
a b c d e f g h i j
4 5 9 3 6 2 10 8 7 1
3 7 4 2 1 6 10 5 8 9
10 9 3 1 2 7 8 5 6 4
5 10 4 9 7 8 1 3 6 2
8 6 5 9 1 4 3 2 7 10
2 8 9 3 5 6 10 1 4 7
3 9 8 2 1 4 10 6 7 5
3 7 2 1 8 6 10 4 5 9
1 10 8 3 6 5 4 2 7 9
7 2 3 5 6 1 10 4 8 9
# cat test_data |
sed -rn '1{h;d};s/[0-9]{2,}|[6-9]/0/g;G;s/\n|$/ &/g;s/$/&1 2 3 4 5 /;:a;s/^(\S*) (.*\n)(\S* )(.*)/\2\4\1\3/;ta;s/\n//;s/0[^ ]? //g;:b;s/([1-5])(.*)\1(.)/\3\2/;tb;p'
j f d a b      
e d a c h      
d e c j h      
g j h c a      
e h g f c      
h a d i e      
e d a f j      
d c a h i      
a h d g f      
f b c h d   
sed
命令的工作原理如下

数据文件的第一行包含列标题,存储在保留空间中,然后是模式空间(当前行)已删除。对于所有后续数据行,所有两个或多个数字和值6到9都转换为0。列名将被追加,并在数据值中添加换行符。换行符和字符串结尾之前插入空格。数据将转换为查找,并在其前面添加排序值,即1 2 3 4 5。换行符与任何0值和关联的查找一起删除。值1到5将替换为查找中的列名

编辑:


我可能误解了有关列或行排序的问题,如果是这样的话,这是一个最小的解决方案-用原始值替换
1 2 3 4 5
,并在用查找中的列名替换数字数据之前执行数字排序。

您的输入数据看起来如何?我想
=5
应该读
>5
GNU awk4.0也有。Dimitre-谢谢你让我知道。刚刚看到David的评论。不,你没有帮我做作业,但非常感谢你的建议