在linux中如何移动数字并与列和行匹配?

在linux中如何移动数字并与列和行匹配?,linux,awk,Linux,Awk,嗨,伙计们,我有一个问题??我想在另一个文件中移动列,并与行和列匹配,然后放在准确的位置 输入文件1是: COURSE NAME: Java CREDITS: 4 200345 88 300126 78 287136 68 200138 71 COURSE NAME: Operating System CREDITS: 4 287136 86 200138 72 200345 77 300056 78 我试了很多:( 你能帮我吗?我写了一个快速而肮

嗨,伙计们,我有一个问题??我想在另一个文件中移动列,并与行和列匹配,然后放在准确的位置

输入文件1是:

COURSE NAME: Java CREDITS: 4 200345 88 300126 78 287136 68 200138 71 COURSE NAME: Operating System CREDITS: 4 287136 86 200138 72 200345 77 300056 78 我试了很多:(
你能帮我吗?

我写了一个快速而肮脏的解决方案,适用于给定的示例输入

命令:

 sed '/CREDIT/d' file1|awk 'FNR==NR{ if($0~/Java/){j++;o=0;next;}
        if($0~/Operating/){o++;j=0;next;}
        if(j){java[$1]=$2}
        if(o){os[$1]=$2}
}NR>FNR{OFS=" ";
        if(FNR==1){sub(/ /,"");print;}
        else{$2=" "
        $3=($1 in java)?java[$1]:"-";
        $4=($1 in os)?os[$1]:"-";
        print $0;
        }

}' - file2|column -t|sed -e 's/ID/ ID/' -e '2,${s/ /    /}'
在我的控制台上测试:

kent$  sed '/CREDIT/d' file1|awk 'FNR==NR{ if($0~/Java/){j++;o=0;next;}
        if($0~/Operating/){o++;j=0;next;}
        if(j){java[$1]=$2}
        if(o){os[$1]=$2}
}NR>FNR{OFS=" ";
        if(FNR==1){sub(/ /,"");print;}
        else{$2=" "
        $3=($1 in java)?java[$1]:"-";
        $4=($1 in os)?os[$1]:"-";
        print $0;
        }

}' - file2|column -t|sed -e 's/ID/ ID/' -e '2,${s/ /    /}'
STUDENT ID  Java  Operating  System  GPA
200138        71    72
200345        88    77
287136        68    86
300056        -     78
300126        78    -

实际上,逻辑部分相对简单,在您的示例中,许多代码只是用于以相同的格式进行输出。

您可以使用
awk
完成这项工作,但这并不简单。如下所示:

# We will save every course name in an array for the report, but first remove the 
# the unwanted space from it's name. This line only works on the COURSE NAME lines
/^COURSE NAME/ {cn=gensub(" ","_","g",gensub(".*: ","","g",$0)); crss[cn]+=1 }

# On lines which starts with a number (student id), we are saving the student ids 
# in an array (stdnts) and the students score with a "semi" multideminsional array/hash
# where the indecies are "student_id-course_name" 
/^[0-9]/ {stdnts[$1]+=1 ; v[$1 "-" cn]=$2}

# after the above processing (e.g. the last line of the input file)
END {
      # print the header, it's dynamic and uses the course names it saved earlier
      printf("%-20s","STUDENT ID");
      for (e in crss) {printf("%-20s",e)}
      printf("%-20s\n","GPA")

      # print the report
      for (s in stdnts)
          # we need to print every student id
          { printf("%-20s",s)
            for (cs in crss) {
                # then check if she had any score for every score, and print it
                if (v[s "-" cs] > 0) {
                    printf("%-20s",v[s "-" cs])
                }
                else {
                    printf("%-20s","-")
            }
          }
        printf("%-20s\n"," ")
      }
  }
请参见此处的操作:

注:

  • 脚本没有优化
  • 它将原来的课程名称替换为无空格的课程名称
  • 学生表的输出不按学生id排序

  • 它只需要第一个文件作为输入!将上述文件放入类似于
    report.awk
    的文件中,然后执行
    awk-f report.awk input_文件

  • HTH

    相关:我刚刚添加了一些评论。Thanx dude,我还有一个问题。你没有写任何文件名。你能告诉我把我的文件名(文件1和文件2)放在哪里吗。把上面的内容放在一个像
    report.awk
    这样的文件中,然后做
    awk-f report.awk INPUT\u file
    。它只需要第一个文件作为输入。
     sed '/CREDIT/d' file1|awk 'FNR==NR{ if($0~/Java/){j++;o=0;next;}
            if($0~/Operating/){o++;j=0;next;}
            if(j){java[$1]=$2}
            if(o){os[$1]=$2}
    }NR>FNR{OFS=" ";
            if(FNR==1){sub(/ /,"");print;}
            else{$2=" "
            $3=($1 in java)?java[$1]:"-";
            $4=($1 in os)?os[$1]:"-";
            print $0;
            }
    
    }' - file2|column -t|sed -e 's/ID/ ID/' -e '2,${s/ /    /}'
    
    kent$  sed '/CREDIT/d' file1|awk 'FNR==NR{ if($0~/Java/){j++;o=0;next;}
            if($0~/Operating/){o++;j=0;next;}
            if(j){java[$1]=$2}
            if(o){os[$1]=$2}
    }NR>FNR{OFS=" ";
            if(FNR==1){sub(/ /,"");print;}
            else{$2=" "
            $3=($1 in java)?java[$1]:"-";
            $4=($1 in os)?os[$1]:"-";
            print $0;
            }
    
    }' - file2|column -t|sed -e 's/ID/ ID/' -e '2,${s/ /    /}'
    STUDENT ID  Java  Operating  System  GPA
    200138        71    72
    200345        88    77
    287136        68    86
    300056        -     78
    300126        78    -
    
    # We will save every course name in an array for the report, but first remove the 
    # the unwanted space from it's name. This line only works on the COURSE NAME lines
    /^COURSE NAME/ {cn=gensub(" ","_","g",gensub(".*: ","","g",$0)); crss[cn]+=1 }
    
    # On lines which starts with a number (student id), we are saving the student ids 
    # in an array (stdnts) and the students score with a "semi" multideminsional array/hash
    # where the indecies are "student_id-course_name" 
    /^[0-9]/ {stdnts[$1]+=1 ; v[$1 "-" cn]=$2}
    
    # after the above processing (e.g. the last line of the input file)
    END {
          # print the header, it's dynamic and uses the course names it saved earlier
          printf("%-20s","STUDENT ID");
          for (e in crss) {printf("%-20s",e)}
          printf("%-20s\n","GPA")
    
          # print the report
          for (s in stdnts)
              # we need to print every student id
              { printf("%-20s",s)
                for (cs in crss) {
                    # then check if she had any score for every score, and print it
                    if (v[s "-" cs] > 0) {
                        printf("%-20s",v[s "-" cs])
                    }
                    else {
                        printf("%-20s","-")
                }
              }
            printf("%-20s\n"," ")
          }
      }