Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/linux/22.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Linux 如何消除文件中int值之间的间隙?_Linux_Bash_Shell_Awk_Command Line - Fatal编程技术网

Linux 如何消除文件中int值之间的间隙?

Linux 如何消除文件中int值之间的间隙?,linux,bash,shell,awk,command-line,Linux,Bash,Shell,Awk,Command Line,给定一个包含两列整数的文件,我想消除整数值之间的间隙。我的意思是,如果我们取两个整数A和B,在某种程度上没有C,比如A 1 2 1 3 2 5 6 9 3 5 7 9 11 6 7 11 为此: 1 2 1 3 2 4 5 7 3 4 6 7 8 5 6 8 在前两列中,当前整数为{1,2,3,5,6,7,9,11}。缺少的值是{4,8,10}。目标是将每个整数减少小于它的缺失值的数量。 因此,5、6和7减少了1,9 us减少了2,11 us减少了3。 所以值{1,2,3,5,6,7,9,

给定一个包含两列整数的文件,我想消除整数值之间的间隙。我的意思是,如果我们取两个整数A和B,在某种程度上没有C,比如A
1 2
1 3
2 5
6 9
3 5
7 9
11 6
7 11
为此:

1 2 
1 3
2 4
5 7
3 4
6 7
8 5
6 8
在前两列中,当前整数为{1,2,3,5,6,7,9,11}。缺少的值是{4,8,10}。目标是将每个整数减少小于它的缺失值的数量。 因此,5、6和7减少了1,9 us减少了2,11 us减少了3。 所以值{1,2,3,5,6,7,9,11}被{1,2,3,4,5,6,7,8}替换。 有人知道如何使用linux命令、bash脚本或awk命令高效地完成这项工作吗? 谢谢大家!

编辑: 我试着去做,但是我没有找到一种在shell脚本中实现的方法,我必须编写一个执行shell脚本的c程序。 第一部分只是对文件进行排序,第二部分是我在问题中提到的

#包括
#包括
#包括
#包括
#定义最大整数100000000
无效进程_文件(字符*路径){
//第一部分
char*outpath=“tmpfile”;
char*command=calloc(456+3*strlen(path)+strlen(outpath),sizeof(char));
sprintf(command,“#!/bin/bash\nvar1=$(cat%s | head-n4&&(cat%s | tail-n+5 | awk'{split($0,a,\“\”);asort(a);for(i=1;i这可以做到:

awk '(NR==FNR){for(i=1;i<=NF;++i) {a[$i]; max=(max<$i?$i:max)};next}
     (FNR==1) {for(i=1;i<=max;++i) if(i in a) a[i]=++c }
     {for(i=1;i<=NF;++i) $i=a[$i]}1' file file
上述命令将返回:

1 2
1 3
2 4
5 7
3 4
6 7
8 5
6 8
此方法的思想是跟踪数组
a
,该数组由旧值索引并返回新值:
a[old]=new
。我们扫描文件两次,并将所有可能的值存储在
a[old]中
。当我们第二次读取文件时,我们首先检查新值将是什么。完成后,我们只需用新值更新所有字段并打印结果

也可以通过一次性读取文件来完成上述操作,只需缓冲一点:

awk '{b[FNR]=$0;for(i=1;i<=NF;++i) {a[$i]; max=(max<$i?$i:max)}}
     END {
        for(i=1;i<=max;++i) if(i in a) a[i]=++c
        for(n=1;n<=FNR;++n) {
          $0=b[n]
          for(i=1;i<=NF;++i) $i=a[$i]
          print
        }
     }' file

awk'{b[FNR]=$0;for(i=1;i假设您的输入如下所示:

input.txt

2 1
4 3
5 5
6 2
1 4
8 7
9 6
7 9
注意:col1中没有3,col2中没有8,只是为了便于跟踪

然后分别对每列进行排序并存储:

$sort -k1,1 input.txt | awk '{ print $1}'  > 1_sorted
$cat 1_sorted
1
2
4
5
6
7
8
9


$sort -k2,2 input.txt | awk '{ print $2}'  > 2_sorted
$cat 2_sorted
1
2
3
4
5
6
7
9
现在只需合并两个文件:

$paste -d' ' 1_sorted 2_sorted > merged_again

$ cat merged_again
1 1
2 2
4 3
5 4
6 5
7 6
8 7
9 9

可能有一种性能更高/更优雅的方法,但我现在想不起来。

使用GNU awk和
asorti()


@我明白了,但问题是,在我看来,这似乎是一件简单的事情,我似乎没有找到一种有效的方法,我补充了我试图做的do@Inian我添加了我尝试过的内容,但它不起作用的原因是执行时间太长,因为我使用sed将每一行替换为新值,时间复杂度为n^2,我我在寻找一种更有效的方法。我想我的大问题是-为什么?你想创建一个特定的输出吗?然后忽略这个,只写那个输出。如果你特别想做的是根据规则编辑这个文件,那么我不清楚规则。下面的答案中有一些好的想法。这是你选择的在这组复杂的
c
代码中调用
sed
表示您不熟悉
awk
。它使像您这样的任务能够在一个进程中处理所有任务,并将显著减少您的运行时间。有了JohnBrown的解决方案,您甚至可以使用内置功能来减少代码库。不确定您的ata可以工作,但希望您知道*nix utitilty
tsort
(地形排序)。它可能是您工具箱的另一个好工具。祝您好运!哦,还有++通过显示代码来改进您的Q。祝您好运。不是我,但我只是尝试了一下,它没有提供所需的输出:您的文件看起来像什么?(关于我的输入,请参见我的答案)我想你没有理解我的问题,请看一下我的例子和我的程序。值的位置不重要,重要的是如果我们取任意两个不同的整数a和B,其中a>B,并且文件中没有整数C,比如CB,那么a-B=1。为此,我列出了最小和最大值之间的所有整数文件中的st integer,我指的是不存在于文件中。然后,对于文件中的每个整数,我将其值减少为小于它的缺失整数的数量。很明显,我认为@kvantour是您想要的解决方案
$paste -d' ' 1_sorted 2_sorted > merged_again

$ cat merged_again
1 1
2 2
4 3
5 4
6 5
7 6
8 7
9 9
$ gawk '{                         # GNU awk only or implement sort
    a[$1];a[$2]                   # hash field values to a array
    f1[NR]=$1;f2[NR]=$2           # hash fields $1 and $2 index on NR
}
END {                             # after all data is hashed
    asorti(a,a,"@ind_num_asc")    # sort index of a where the values are
    for(i in a)                   # make a reverse map 
        b[a[i]]=i
    for(i=1;i<=NR;i++)            # iterate the stored "records"
        print b[f1[i]],b[f2[i]]   # print and fetch from reverse map
}' file
1 2
1 3
2 4
5 7
3 4
6 7
8 5
6 8