Awk 如何从一个文件中grep数据,执行小操作,然后将它们附加到另一个文件中

Awk 如何从一个文件中grep数据,执行小操作,然后将它们附加到另一个文件中,awk,sed,grep,Awk,Sed,Grep,我有两个文件 一个是(案例1): Automatically generated mesh 10 Reciprocal lattice 0.00000000000000 0.00000000000000 0.00000000000000 1 0.20000000000000 -0.00000000000000 -0.00000000000000 8 0.40000000000000 -0.

我有两个文件 一个是(案例1):

Automatically generated mesh
      10
Reciprocal lattice
    0.00000000000000    0.00000000000000    0.00000000000000             1
    0.20000000000000   -0.00000000000000   -0.00000000000000             8
    0.40000000000000   -0.00000000000000   -0.00000000000000             8
    0.20000000000000    0.20000000000000   -0.00000000000000             6
    0.40000000000000    0.20000000000000   -0.00000000000000            24
   -0.40000000000000    0.20000000000000    0.00000000000000            24
   -0.20000000000000    0.20000000000000    0.00000000000000            12
    0.40000000000000    0.40000000000000   -0.00000000000000             6
   -0.40000000000000    0.40000000000000    0.00000000000000            12
   -0.40000000000000    0.40000000000000    0.20000000000000            24
另一个是(案例2)

我需要

  • grep倒数晶格中
    k点和权重之间的数据:生成的k路径。
    和它之后的第一个空行
    (即在分数坐标(直接晶格)中具有离子位置的行之前)
    case2文件并将最后一列设置为
    0
  • 倒数格
    之后,计算案例1文件中的总行数,以及在步骤1中显示的文件中的总行数,然后 使用案例1第二行中的可用编号更新此编号 文件此处为10,但可能有所不同)
  • 将第一步中的灰色数据附加到第一个文件中。并将第一个文件复制为KPOINTS
  • 最后的KPOINTS文件应为

    Automatically generated mesh
          27
    Reciprocal lattice
        0.00000000000000    0.00000000000000    0.00000000000000             1
        0.20000000000000   -0.00000000000000   -0.00000000000000             8
        0.40000000000000   -0.00000000000000   -0.00000000000000             8
        0.20000000000000    0.20000000000000   -0.00000000000000             6
        0.40000000000000    0.20000000000000   -0.00000000000000            24
       -0.40000000000000    0.20000000000000    0.00000000000000            24
       -0.20000000000000    0.20000000000000    0.00000000000000            12
        0.40000000000000    0.40000000000000   -0.00000000000000             6
       -0.40000000000000    0.40000000000000    0.00000000000000            12
       -0.40000000000000    0.40000000000000    0.20000000000000            24
       0.00000000  0.00000000  0.00000000       0
       0.05555556  0.00000000  0.05555556       0
       0.11111111  0.00000000  0.11111111       0
       0.16666667  0.00000000  0.16666667       0
       0.22222222  0.00000000  0.22222222       0
       0.27777778  0.00000000  0.27777778       0
       0.33333333  0.00000000  0.33333333       0
       0.38888889  0.00000000  0.38888889       0
       0.44444444  0.00000000  0.44444444       0
       0.50000000  0.00000000  0.50000000       0
       0.50000000  0.00000000  0.50000000       0
       0.51388889  0.02777778  0.51388889       0
       0.52777778  0.05555556  0.52777778       0
       0.54166667  0.08333333  0.54166667       0
       0.55555556  0.11111111  0.55555556       0
       0.50000000  0.02777778  0.52777778       0
       0.50000000  0.00000000  0.50000000       0
    
    使用GNU awk:

    awk 'FNR==NR && /^Reciprocal lattice/ { scnt=1;next } FNR==NR && scnt==1 { cnt++;map1[FNR]=$0 } NR != FNR  && /^$/ { scnt1=0 } FNR != NR  && / k-points in reciprocal lattice and weights: K-Path Generated./ { scnt1=1;next } FNR != NR && scnt1==1 { cnt++;gsub($4,"0",$4);map[FNR]=$0 } END { PROCINFO["sorted_in"]="@ind_num_asc";print "Automatically generated mesh";printf "\t%s\n",cnt;print "Reciprical lattice";for (i in map1) { print map1[i] } for (i in map) { print map[i] } }' case1 case2
    
    说明:

    awk 'FNR==NR && /^Reciprocal lattice/ {                        # Process the first file (FNR==NR). Where the line start with "Reciprocal lattice" set a marker variable scnt to 1
                  scnt=1;
                  next 
                } 
         FNR==NR && scnt==1 {                                       # Where it is the first file and marker scnt is 1, process
                  cnt++;                                            # Increment a total line counter
                  map1[FNR]=$0                                      # Set up a map array with the file record number the index and the line ($0) the value
                }
         NR != FNR  && /^$/ {                                       # Process where we encounter the second file (NR != FNR) and the line is blank
                  scnt1=0                                           # Set second tracking variable scnt1 to 0
                } 
         FNR != NR  && / k-points in reciprocal lattice and weights: K-Path Generated./ { 
                  scnt1=1;                                          # Where it is the second file and we see the text "k-point ...", set second tracking variable scnt1 to 1
                  next 
                } 
         FNR != NR && scnt1==1 {                                     # Process where second file and second tracking variable is 1
                  cnt++;                                             # Increment total line count
                  gsub($4,"0",$4);                                   # Use gsub to replace the 4th field with 0
                  map[FNR]=$0                                        # Set up another array map with the file number record as the index and the amended line as the value
                 } 
             END {                                                   # Process at the end of processing both files.
                  PROCINFO["sorted_in"]="@ind_num_asc";              # Set the array ordering
                  print "Automatically generated mesh";                            
                  printf "\t%s\n",cnt;print "Reciprical lattice";    # Print text and total
                  for (i in map1) { 
                     print map1[i]                                   # Loop through map1 and print lines
                  } 
                  for (i in map) { 
                     print map[i]                                    # Loop through map and print lines
                  } 
                 }' case1 case2
    

    如果您继续添加到我的原始注释中,您可以构建一个简短的
    awk
    脚本,它将为您处理整个转换过程。你基本上有两套规则。我们将首先读取的
    case2
    文件的规则,您可以比较
    FNR
    (文件记录编号)等于
    NR
    (记录编号),这意味着您正在读取第一个文件

    对于要读取的第二个文件,
    case1
    NR
    继续增加,因此当前的
    FNR
    不再等于总的
    NR
    ——这是在同一脚本中以不同方式处理每个文件的方便方法

    对于
    case2
    case1
    文件,您可以执行以下操作:

    awk '
        NR==FNR && /k-points/ { c2=1; next }
        NR==FNR && !NF { m=c2; c2=0 }
        NR==FNR && c2  { sub($NF,"0"); b[c2++] = $0 }
        
        NR!=FNR && /Reciprocal/ { n=1; next } 
        NR!=FNR && n  { a[n++] = $0 }
    END {
        print "Automatically generated mesh"
        print "       " m + n - 2
        print "Reciprocal lattice"
        for (i=1; i<n; i++)
            print a[i]
        for (i=1; i<m; i++)
            print b[i]
    }' case2 case1
    

    如果您还有其他问题,请告诉我。

    好的,您被困在哪里了
    awk
    可以处理整个事情。我被困在步骤1。用
    awk'/k-points/{n=1;next}隔离案例2中的记录;NF==0{n=0};n{sub($NF,“0”);print}'case2
    确认这是您从case2中需要的内容,然后不打印输出,而是保存到数组并移动到步骤2。(您可以使用数组索引作为计数器)
    n
    只是一个标志,当设置为
    1
    时,它会在
    的“k点”
    行之后收集记录,直到找到一个空行
    $NF==0
    ,并且
    n
    被设置回零。它不起作用。谢谢你抽出时间。大卫先生的建议部分奏效了,不用担心。我可以使用GNU awk 4.0.2和您发布的示例验证该解决方案是否有效。啊,我现在知道了。我的集群上没有gnuplot,而且我也无法在其上安装gnu。这就是为什么它对我不起作用的原因。有很多单字母变量名(a,b,m,n,c2)-一些有意义的名称会使代码更容易理解。为什么
    c2
    而不是
    c
    (当然,如果你重命名它,那就无关紧要了)?还可以考虑创建一个单<代码> NR==FNR{…} } /Cuth>块,这样就不必测试<代码> NR==FNR 3次和<代码> NR!FNR两次。@EdMorton-是的,这是非常正确的。我开始使用array1,array2,但后来我测试的一个线性程序变得很长。。。我将来会抵制这种诱惑。
    :)
    awk '
        NR==FNR && /k-points/ { c2=1; next }
        NR==FNR && !NF { m=c2; c2=0 }
        NR==FNR && c2  { sub($NF,"0"); b[c2++] = $0 }
        
        NR!=FNR && /Reciprocal/ { n=1; next } 
        NR!=FNR && n  { a[n++] = $0 }
    END {
        print "Automatically generated mesh"
        print "       " m + n - 2
        print "Reciprocal lattice"
        for (i=1; i<n; i++)
            print a[i]
        for (i=1; i<m; i++)
            print b[i]
    }' case2 case1