어떻게 파일에 INT 값 사이의 차이를 제거하는 방법은 무엇입니까?

Hichem97 :

정수의 두 개의 열이 포함 된 파일을 감안할 때, 나는 정수 값 사이의 간격을 제거하고 싶습니다. 간격으로 나는 우리가 두 개의 정수 A와 B를 가지고가는 경우에, 방법으로 이러한 어떠한 C가 없다는 것을 의미

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}입니다. 목표는보다 작은 값 누락의 숫자로 모든 정수를 감소하는 것입니다. {1,2,3,5,6,7,9,11 값이 {1}로 대체되도록 5,6- 7 있으므로, 9 (3)에 의해 우리가 2만큼 감소, 1만큼 감소되고, 11 저하 2,3,4,5,6,7,8}. 누구 아는 방법 리눅스 명령, bash는 스크립트 나하고 AWK 명령을 사용하여 효율적으로 작업을 수행 할 수 있습니까? 감사합니다!

편집 : 나는 그것을 시도하지만 쉘 스크립트에서 할 수있는 방법을 찾아야하지 않았다, 내가 실행하는 쉘 스크립트 교류 프로그램을 작성했다. 첫 번째 부분은, 파일, 두 번째 정렬 나는이 문제에 대해 이야기 어떤 않습니다.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>


#define MAX_INTS 100000000

void process_file(char *path){
    //FIRST PART
    char *outfpath="tmpfile";
    char *command=calloc(456+3*strlen(path)+strlen(outfpath),sizeof(char));

    sprintf(command,"#!/bin/bash \nvar1=$( cat %s | head -n 4  && ( cat %s | tail -n +5  | awk '{split( $0, a, \" \" ); asort( a ); for( i = 1; i <= length(a); i++ ) printf( \"%c%c \", a[i] ); printf( \"\\n\" ); }' | sort -n -k1,1 -k2 | uniq) )\nvar2=$( ( (echo \"$var1\" | tail -n +5 | cut -f 1 -d\" \") && (echo \"$var1\" | tail -n +5 | cut -f 2 -d\" \" ) ) | sort -n -k1,1 | uniq | awk '{for(i=p+1; i<$1; i++) print i} {p=$1}' )\necho \"$var1\" > %s\necho \"$var2\"| tr \"\\n\" \" \" > %s",path,path,'%','s',path,outfpath);

    if(system(command)==-1){
        fprintf(stderr,"Erreur à l'exécution de la commande \n%s\n",command);
    }
    //the first part only sorts the file and puts in outpath the list of the missing integers

    //SECOND PART
    long unsigned start=0,end=0,val,index=0;
    long unsigned *intvals=calloc(MAX_INTS,sizeof(long unsigned));
    FILE *f=fopen(outfpath,"r");

    //reads the files and loads the missing ints to the array intvals
    while(fscanf(f,"%lu ",&val)==1){
        end=index;
        intvals[index]=val;
        index++;
    }
    if (index==0) return;
    intvals=realloc(intvals,index*sizeof(long unsigned));
    fclose(f);
    free(command);


    f=fopen(path,"r+w");
    char *line=calloc(1000,sizeof(char));
    command=calloc(1000,sizeof(char));
    char *str;
    long unsigned v1,v2,
        d1=0,d2=0,
        c=0,prec=-1,start_l=0;
    int pos1, pos2;  

    //read a file containing two columns of ints 
    //for each pair v1 v2, count d1 d2, 
    //such as d1 is the number of missing values smaller than v1, d2 the number of missing values smaller than v2
    //and overrwrite the line in the file using sed with the values v1-d1 and v2-d2

    while(fgets(line,1000,f)!=NULL && line[0]=='#'){ continue; }

    do{
        str=strtok(line," \t");
        v1=atoi(str);
        str=strtok(NULL," \t");
        v2=atoi(str);
        if(prec!=v1) {
            prec=v1;
            d2=d1;
            start_l=start;
        }
        for(index=start;index<=end;index++){ 
            if(intvals[index]<v1){ 
                 d1++; 
                 start++;
                 c=1;
            }else{
                start=d1;
                break;
            }
        }
        for(index=start_l;index<=end;index++){ 
            if(intvals[index]<v2){ 
                d2++; 
                start_l++;
                c=1; 
            }else{ 
                break;
            }
        }         
        if(c){
            sprintf(command,"sed -i 's/%lu %lu/%lu %lu/' %s",v1,v2,v1-d1,v2-d2,path);
            if(system(command)==-1){
                fprintf(stderr,"Erreur à l'exécution de la commande \n%s\n",command);
            }
        }
        c=0;
    }while(fgets(line,1000,f)!=NULL);
    fclose(f);
    free(command);
    free(line);
    free(intvals);
}



int main(int argc,char* argv[]){

    process_file(argv[1]);
    return 0;
}    
kvantour :

이 그것을 할 수 있습니다

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

경우 file입력으로있다 :

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

이 방법의 아이디어는 배열의 트랙을 유지하는 것입니다 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

추천

출처http://43.154.161.224:23101/article/api/json?id=15580&siteId=1