Indexing 找出列中每个字段的范围

Indexing 找出列中每个字段的范围,indexing,awk,range,tcl,Indexing,Awk,Range,Tcl,我有一个这样的专栏: A 1 B 3 C 5 D 4 E 7 F 1 G 1 H 3 对于第#2列中的每个字段,我要计算上下3个字段半径的范围(max-min) A range(1 3 5 4) B range(1 3 5 4 7) C range(1 3 5 4 7 1) D range(1 3 5 4 7 1 1) E range( 3 5 4 7 1 1 3) F range( 5 4 7 1 1 3) G range( 4 7 1 1 3) H range(

我有一个这样的专栏:

A 1
B 3
C 5
D 4
E 7
F 1
G 1
H 3
对于第#2列中的每个字段,我要计算上下3个字段半径的范围(max-min)

A range(1 3 5 4)
B range(1 3 5 4 7)
C range(1 3 5 4 7 1)
D range(1 3 5 4 7 1 1)
E range(  3 5 4 7 1 1 3)
F range(    5 4 7 1 1 3)
G range(      4 7 1 1 3)
H range(        7 1 1 3)
如何在awk中实现这一点


我可以在perl中使用以下命令执行同样的操作:

my $set_size = @values;
for ( my $i = 0 ; $i < $set_size ; $i++ ) {
    my $min = $i - 4;
    if ( $min < 0 ) { $min = 0; }
    my $max = $i + 4;
    if ( $max > ( $set_size - 1 ) ) { $max = $set_size - 1; }
    my $min_val = $values[$min];
    my $max_val = $values[$min];
    for ( my $j = $min ; $j <= $max ; $j++ ) {
        if ( $values[$j] <= $min_val ) { $min_val = $values[$j]; }
        if ( $values[$j] >= $max_val ) { $max_val = $values[$j]; }
    }
    my $range = $max_val - $min_val;
    printf "$points[$i] %.15f\n", $range;
}
my$set\u size=@值;
对于(我的$i=0;$i<$set\u size;$i++){
my$min=$i-4;
如果($min<0){$min=0;}
我的$max=$i+4;
如果($max>($set\u size-1)){$max=$set\u size-1;}
我的$min_val=$values[$min];
我的$max_val=$values[$min];
对于(my$j=$min;$j,在shell提示符下:

bash$ txr -c '@(collect)
@label @num
@(end)
@(bind rng @[window-map 3 nil (opip list (remq nil) (mapcar toint)) num])
@(output)
@  (repeat)
@label range(@rng) -> @(find-min rng)..@(find-max rng) 
@  (end)
@(end)' 
A 1
B 3
C 5
D 4
E 7
F 1
G 1
H 3
[Ctrl-D][Enter]
A range(1 3 5 4) -> 1..5 
B range(1 3 5 4 7) -> 1..7 
C range(1 3 5 4 7 1) -> 1..7 
D range(1 3 5 4 7 1 1) -> 1..7 
E range(3 5 4 7 1 1 3) -> 1..7 
F range(5 4 7 1 1 3) -> 1..7 
G range(4 7 1 1 3) -> 1..7 
H range(7 1 1 3) -> 1..7 

idk我想计算3个场半径上下的范围(最大-最小值)。
的意思是,要从发布的输入中获得发布的输出,应该是:

$ cat tst.awk
{
    keys[NR] = $1
    values[NR] = $2
}
END {
    range = 3
    for (i=1; i<=NR; i++) {
        min = ( (i - range) >= 1  ? i - range : 1  )
        max = ( (i + range) <= NR ? i + range : NR )
        printf "%s range(", keys[i]
        for (j=min; j<=max; j++) {
            printf "%s%s", values[j], (j<max ? " " : ")\n")
        }
    }
}
$
$ awk -f tst.awk file
A range(1 3 5 4)
B range(1 3 5 4 7)
C range(1 3 5 4 7 1)
D range(1 3 5 4 7 1 1)
E range(3 5 4 7 1 1 3)
F range(5 4 7 1 1 3)
G range(4 7 1 1 3)
H range(7 1 1 3)
$cat tst.awk
{
钥匙[NR]=$1
数值[NR]=2美元
}
结束{
范围=3
对于(i=1;i=1?i-范围:1)

max=((i+range)您的示例perl没有打印出您的示例输出,它似乎做了一些不同的事情……下面是我在perl中的做法:

!/usr/bin/perl
使用警告;
严格使用;
使用功能qw/say/;
使用列表::Util qw/min max/;
我的(@col1,@col2);
而(){
咀嚼;
我的($v1,$v2)=分割;
推动@col1,$v1;
推送@col2,$v2;
}
我的@前缀;
对于我的$i(0..$#col1){
我的@range=@col2[max($i-3,0)…min($i+3,$#col2)];
如果$i>3,则按@prefix';
取消移位@范围,@前缀;
说“$col1[$i]范围(@range)”
}
运行它:

$ perl range.pl input.txt
A range(1 3 5 4)
B range(1 3 5 4 7)
C range(1 3 5 4 7 1)
D range(1 3 5 4 7 1 1)
E range(  3 5 4 7 1 1 3)
F range(    5 4 7 1 1 3)
G range(      4 7 1 1 3)
H range(        7 1 1 3)
但是,如果任何数字大于9,则格式将中断。

因为您标记了:

!/usr/bin/env tclsh
lassign$argv文件大小
设置fh[打开$r文件]
#假设每行正好有两个空格分隔的单词
设置数据[dict create{*}[split[read-nonewline$fh]]
收盘价$fh
设置len[dict size$数据]
设置值[dict值$data]
设置i 0
{key}$data的dict{
首先设置[expr{max($i-$size,0)}]
设置最后一个[expr{min($i+$size,$len)}]
放入[格式“%s”范围(%s%s)”\
$key\
[字符串重复“$first]\
[lrange$values$first$last]\
]
增量i
}
输出

A range(1 3 5 4)
B range(1 3 5 4 7)
C range(1 3 5 4 7 1)
D range(1 3 5 4 7 1 1)
E range(  3 5 4 7 1 1 3)
F range(    5 4 7 1 1 3)
G range(      4 7 1 1 3)
H range(        7 1 1 3)

不使用awk怎么能做到这一点呢?即使您不知道要使用的特定工具的确切语法,也至少要为您要使用的算法提供伪代码,这样您就可以自己尝试解决问题。我可以在perl中使用:my$set_size=@values;for(my$I=0;$I<$set_size;$I++){my$min=$i-4;if($min<0){$min=0;}my$max=$i+4;if($max>($set_size-1)){$max=$set_size-1;}my$min_val=$values[$min];my$max_val=$values[$min];for(my$j=$min;$j我在上通过perl格式化程序运行了您评论中的代码,并将其放入问题中。当然,idk它的确切含义是什么,但可能其他人会这样做。但是,如果您知道如何使用perl进行此操作,为什么要使用awk进行此操作?为什么要将问题标记为
tcl
?perl不会打印您的示例输出。(它也可以重写为长度的一小部分,更清晰…)为什么要用用户没有表示要使用的语言发布解决方案?@DonalFellows我将该语言作为其作者进行推广。