我正在写一个bash脚本,它需要搜索数组中最小的可用整数并将其管道化为变量。
我知道如何识别数组中的最小或最大整数,但我无法弄清楚如何识别'缺失的'最小整数。
示例数组:
1
2
4
5
6
在这个例子中,我需要3作为变量。
答案 0 :(得分:5)
使用sed这将是愚蠢的。使用GNU awk,你可以做到
array=(1 2 4 5 6)
echo "${array[@]}" | awk -v RS='\\s+' '{ a[$1] } END { for(i = 1; i in a; ++i); print i }'
...记住所有数字,然后从1开始计算,直到找到一个它不记得并打印出来的数字。然后你可以用bash记住这个数字
array=(1 2 4 5 6)
number=$(echo "${array[@]}" | awk -v RS='\\s+' '{ a[$1] } END { for(i = 1; i in a; ++i); print i }')
但是,如果您已经在使用bash,那么您可以在纯粹的bash中做同样的事情:
#!/bin/bash
array=(1 2 4 5 6)
declare -a seen
for i in ${array[@]}; do
seen[$i]=1
done
for((number = 1; seen[number] == 1; ++number)); do true; done
echo $number
答案 1 :(得分:1)
您可以从最小数字迭代到最大数字并获取第一个不存在的元素
use List::Util qw( first );
my @arr = sort {$a <=> $b} qw(1 2 4 5 6);
my $min = $arr[0];
my $max = $arr[-1];
my %seen;
@seen{@arr} = ();
my $first = first { !exists $seen{$_} } $min .. $max;
答案 2 :(得分:1)
此代码将按您的要求执行。它可以通过二进制搜索轻松加速,但以这种方式最清楚地说明了。
数组的第一个元素可以是任何整数,子例程返回序列中不存在的第一个值。如果完整数组是连续的,则返回undef
。
use strict;
use warnings;
use 5.010;
my @data = qw/ 1 2 4 5 6 /;
say first_missing(@data);
@data = ( 4 .. 99, 101 .. 122 );
say first_missing(@data);
sub first_missing {
my $start = $_[0];
for my $i ( 1 .. $#_ ) {
my $expected = $start + $i;
return $expected unless $_[$i] == $expected;
}
return;
}
<强>输出强>
3
100
答案 3 :(得分:1)
这是Perl one liner:
$ echo '1 2 4 5 6' | perl -lane '}
{@a=sort { $a <=> $b } @F; %h=map {$_=>1} @a;
foreach ($a[0]..$a[-1]) { if (!exists($h{$_})) {print $_}} ;'
如果要从管道切换到文件输入:
$ perl -lane '}
{@a=sort { $a <=> $b } @F; %h=map {$_=>1} @a;
foreach ($a[0]..$a[-1]) { if (!exists($h{$_})) {print $_}} ;' file
由于它在过程中被排序,因此输入可以是任意顺序。
答案 4 :(得分:0)
$ cat tst.awk
BEGIN {
split("1 2 4 5 6",a)
for (i=1;a[i+1]==a[i]+1;i++) ;
print a[i]+1
}
$ awk -f tst.awk
3
答案 5 :(得分:0)
这里有一个bash
解决方案(假设数字在文件中,每行一个):
sort -n numbers.txt | grep -n . |
grep -v -m1 '\([0-9]\+\):\1' | cut -f1 -d:
第一部分对数字进行排序,然后为每个数字添加一个序列号,第二部分找到第一个与数组中的数字不对应的序列号。
同样的事情,使用sort和awk(沼泽标准,也没有扩展):
sort -n numbers.txt | awk '$1!=NR{print NR;exit}'
答案 6 :(得分:0)
#!/usr/bin/env perl
use 5.020; # why not?
use strict;
use warnings;
sub increasing_stream {
my $start = int($_[0]);
return sub {
$start += 1 + (rand(1) > 0.9);
};
}
my $stream = increasing_stream(rand(1000));
my $first = $stream->();
say $first;
while (1) {
my $next = $stream->();
say $next;
last unless $next == ++$first;
$first = $next;
}
say "Skipped: $first";
输出:
$ ./tyu.pl 381 382 383 384 385 386 387 388 389 390 391 392 393 395 Skipped: 394
答案 7 :(得分:0)
此处其他答案设置的主题略有不同。输入的值不一定要预先排序:
$ cat test
sort -nu <<END-OF-LIST |
1
5
2
4
6
END-OF-LIST
awk 'BEGIN { M = 1 } M > $1 { next } M == $1 { M++; next }
M < $1 { exit } END { print M }'
$ sh test
3
注意:
BEGIN { M = 1 }
更改为NR == 1 { M = $1 }
。