Linux 补充模式
我在一个文件中有这样的记录:Linux 补充模式,linux,bash,shell,awk,Linux,Bash,Shell,Awk,我在一个文件中有这样的记录: 1867 121 2 56 1868 121 1 6 1868 121 2 65 1868 122 0 53 1869 121 0 41 1869 121 1 41 1871 121 1 13 1871 121 2 194 我希望获得以下输出: 1867 121 2 56 1868 121 1 6 1868 121 2 65 1868 122 0 53 1869 1
1867 121 2 56
1868 121 1 6
1868 121 2 65
1868 122 0 53
1869 121 0 41
1869 121 1 41
1871 121 1 13
1871 121 2 194
我希望获得以下输出:
1867 121 2 56
1868 121 1 6
1868 121 2 65
1868 122 0 53
1869 121 0 41
1869 121 1 41
1870 121 0 0
1871 121 1 13
1871 121 2 194
不同之处在于1870 121 0
行
因此,如果第一列中的数字之间的差异大于1,那么我们必须包括一行缺少的数字(上面的情况是1870
)和其他列。应该以某种方式获得其他列,即第二列是列数的可能值中的最小值(在示例中,这些值可能是121
或122
),并且与第三列的情况相同。最后一列的值始终为零
有人能给我提些建议吗?提前谢谢
我正试图用awk来解决这个问题,但也许还有其他更好或更实用的解决方案……类似的方法可以奏效-
awk 'BEGIN{getline;a=$1;b=$2;c=$3}
NR==FNR{if (b>$2) b=$2; if (c>$3) c=$3;next}
{if ($1-a>1) {x=($1-a); for (i=1;i<x;i++) {print (a+1)"\t"b,c,"0";a++};a=$1} else a=$1;print}' file file
像这样的东西可能有用-
awk 'BEGIN{getline;a=$1;b=$2;c=$3}
NR==FNR{if (b>$2) b=$2; if (c>$3) c=$3;next}
{if ($1-a>1) {x=($1-a); for (i=1;i<x;i++) {print (a+1)"\t"b,c,"0";a++};a=$1} else a=$1;print}' file file
Perl解决方案。应该也适用于大文件,因为它不会将整个文件加载到内存中,而是对文件进行两次检查
#!/usr/bin/perl
use warnings;
use strict;
my $file = shift;
open my $IN, '<', $file or die $!;
my @mins;
while (<$IN>) {
my @cols = split;
for (0, 1) {
$mins[$_] = $cols[$_ + 1] if $cols[$_ + 1] < $mins[$_ ]
or ! defined $mins[$_];
}
}
seek $IN, 0, 0;
my $last;
while (<$IN>) {
my @cols = split;
$last //= $cols[0];
for my $i ($last .. $cols[0]-2) {
print $i + 1, "\t@mins 0\n";
}
print;
$last = $cols[0];
}
#/usr/bin/perl
使用警告;
严格使用;
我的$file=shift;
打开我的$IN,“Perl解决方案。应该也适用于大文件,因为它不会将整个文件加载到内存中,而是对文件进行两次检查
#!/usr/bin/perl
use warnings;
use strict;
my $file = shift;
open my $IN, '<', $file or die $!;
my @mins;
while (<$IN>) {
my @cols = split;
for (0, 1) {
$mins[$_] = $cols[$_ + 1] if $cols[$_ + 1] < $mins[$_ ]
or ! defined $mins[$_];
}
}
seek $IN, 0, 0;
my $last;
while (<$IN>) {
my @cols = split;
$last //= $cols[0];
for my $i ($last .. $cols[0]-2) {
print $i + 1, "\t@mins 0\n";
}
print;
$last = $cols[0];
}
#/usr/bin/perl
使用警告;
严格使用;
我的$file=shift;
在Bash解决方案中打开我的$IN,
# initialize minimum of 2. and 3. column
read no min2 min3 c4 < "$infile"
# get minimum of 2. and 3. column
while read c1 c2 c3 c4 ; do
[ $c2 -lt $min2 ] && min=$c2
[ $c3 -lt $min3 ] && min=$c3
done < "$infile"
while read c1 c2 c3 c4 ; do
# insert missing line(s) ?
while (( c1- no > 1 )) ; do
((no++))
echo -e "$no $min2 $min3 0"
done
# now insert existing line
echo -e "$c1 $c2 $c3 $c4"
no=$c1
done < "$infile"
#至少初始化2个。三,。柱
阅读编号为min2 min3 c4的<$infle“
#至少得到2个。三,。柱
读取c1 c2 c3 c4时;做
[$c2-lt$min2]&&min=$c2
[$c3-lt$min3]&&min=$c3
完成<“$infle”
读取c1 c2 c3 c4时;做
#是否插入缺少的行?
而((c1-no>1));做
((no++)
echo-e“$no$min2$min3 0”
完成
#现在插入现有行
回声-e“$c1$c2$c3$c4”
否=$c1
完成<“$infle”
Bash解决方案:
# initialize minimum of 2. and 3. column
read no min2 min3 c4 < "$infile"
# get minimum of 2. and 3. column
while read c1 c2 c3 c4 ; do
[ $c2 -lt $min2 ] && min=$c2
[ $c3 -lt $min3 ] && min=$c3
done < "$infile"
while read c1 c2 c3 c4 ; do
# insert missing line(s) ?
while (( c1- no > 1 )) ; do
((no++))
echo -e "$no $min2 $min3 0"
done
# now insert existing line
echo -e "$c1 $c2 $c3 $c4"
no=$c1
done < "$infile"
#至少初始化2个。三,。柱
阅读编号为min2 min3 c4的<$infle“
#至少得到2个。三,。柱
读取c1 c2 c3 c4时;做
[$c2-lt$min2]&&min=$c2
[$c3-lt$min3]&&min=$c3
完成<“$infle”
读取c1 c2 c3 c4时;做
#是否插入缺少的行?
而((c1-no>1));做
((no++)
echo-e“$no$min2$min3 0”
完成
#现在插入现有行
回声-e“$c1$c2$c3$c4”
否=$c1
完成<“$infle”
单向使用awk
:
BEGIN {
if ( ARGC > 2 ) {
print "Usage: awk -f script.awk <file-name>"
exit 0
}
## Need to process file twice, duplicate the input filename.
ARGV[2] = ARGV[1]
++ARGC
col2 = -1
col3 = -1
}
## First processing of file. Get min values of second and third columns.
FNR == NR {
col2 = col2 < 0 || col2 > $2 ? $2 : col2
col3 = col3 < 0 || col3 > $3 ? $3 : col3
next
}
## Second processing of file.
FNR < NR {
## Get value of column 1 in first row.
if ( FNR == 1 ) {
col1 = $1
print
next
}
## Compare current value of column 1 with value of previous row.
## Add a new row while difference is bigger than '1'.
while ( $1 - col1 > 1 ) {
++col1
printf "%d\t%d %d %d\n", col1, col2, col3, 0
}
## Assing new value of column 1.
col1 = $1
print
}
结果:
1867 121 2 56
1868 121 1 6
1868 121 2 65
1868 122 0 53
1869 121 0 41
1869 121 1 41
1870 121 0 0
1871 121 1 13
1871 121 2 194
单向使用awk
:
BEGIN {
if ( ARGC > 2 ) {
print "Usage: awk -f script.awk <file-name>"
exit 0
}
## Need to process file twice, duplicate the input filename.
ARGV[2] = ARGV[1]
++ARGC
col2 = -1
col3 = -1
}
## First processing of file. Get min values of second and third columns.
FNR == NR {
col2 = col2 < 0 || col2 > $2 ? $2 : col2
col3 = col3 < 0 || col3 > $3 ? $3 : col3
next
}
## Second processing of file.
FNR < NR {
## Get value of column 1 in first row.
if ( FNR == 1 ) {
col1 = $1
print
next
}
## Compare current value of column 1 with value of previous row.
## Add a new row while difference is bigger than '1'.
while ( $1 - col1 > 1 ) {
++col1
printf "%d\t%d %d %d\n", col1, col2, col3, 0
}
## Assing new value of column 1.
col1 = $1
print
}
结果:
1867 121 2 56
1868 121 1 6
1868 121 2 65
1868 122 0 53
1869 121 0 41
1869 121 1 41
1870 121 0 0
1871 121 1 13
1871 121 2 194
您可以尝试使用python脚本解决此问题,以获得“更好”的解决方案。您可以尝试使用python脚本解决此问题,以获得“更好”的解决方案。我的新年决心…Learn Perl
:)…测试了您的脚本,效果非常好+1我的新年决心…学习Perl
:)…测试了您的脚本,效果非常好+1你能不能把你的内部代码while减少到while((c1 no>1));做代码>。祝大家好运。难道你不能把你的内部代码while减少到while((c1no>1));做代码>。祝大家好运。