1

好的,所以首先要更详细地解释我遇到的问题。我在这里设置了两个变量;一个复制一列数据,另一个复制多列数据...

问题是我想在多列前面附加第一列数据,同时保持它们对齐

当我将它们单独重定向到 Cmain 时,这些循环也会执行我想要的操作;但我需要对他们俩都这样做

#copies first column of original car file to format the atom numbers

 FC=$(awk '{for (i=6; i<=21 ; i++)
 if (NR >= 6 && NR == i)
      print $1}' $carf)


 #copies and formats  the rest of the columns from the .incoor file and sets to variable Col

 col=$(awk '{for (j=6; j <= 21 ; j++)
 if (NR >= 6 && NR == j)
 printf  "%13.8f\t%12.8f\t%12.8f%s%s%s%s%4.3f\n", $2, $3, $4,
 "     XXXX", " 1", "    xx","  " $1"  ", "  0.000"}' $coor)

这就是出问题的地方

 #echos variables and appends to Cmain 
 echo  " $FC   $col" >> Cmain

正在发生的事情的例子;出于某种原因,它需要第二组列并将它们向下移动,并将第一行移动...就像我说的那样,当我单独执行它们时,列对齐并且一切都很好...除了我缺少第一列数据

 U1
U2
U3
U4
C1
C2
C3
C4
U5
U6
U7
U8
C5
C6
C7
C8       0.00000000       0.00000000      0.00000000     XXXX 1    xx  U  0.000
   0.00000000     4.43785037      4.86047726     XXXX 1    xx  U  0.000
   4.86047726     0.00000000      4.86047726     XXXX 1    xx  U  0.000
   4.86047726     4.43785037      0.00000000     XXXX 1    xx  U  0.000
   4.86047726     4.43785037      4.86047726     XXXX 1    xx  C  0.000
   4.86047726     0.00000000      0.00000000     XXXX 1    xx  C  0.000
   0.00000000     0.00000000      4.86047726     XXXX 1    xx  C  0.000
   0.00000000     8.87570074      0.00000000     XXXX 1    xx  U  0.000
   0.00000000    13.31355111      4.86047726     XXXX 1    xx  U  0.000
   4.86047726     8.87570074      4.86047726     XXXX 1    xx  U  0.000
   4.86047726    13.31355111      0.00000000     XXXX 1    xx  U  0.000
   4.86047726    13.31355111      4.86047726     XXXX 1    xx  C  0.000
   4.86047726     8.87570074      0.00000000     XXXX 1    xx  C  0.000
   0.00000000    13.31355111      0.00000000     XXXX 1    xx  C  0.000
   0.00000000     8.87570074      4.86047726     XXXX 1    xx  C  0.000

~

我想要的是

  U1    0.00000000     0.00000 etc
  U2    0.00000000     4.43785037      4.86047726 .......
4

2 回答 2

2

您正在寻找paste(1)命令。 echo不能将一个字符串拼接到另一个字符串(这似乎是您正在寻找的,真的;在字符串 2 中的每个新行之前,插入字符串 1 的下一行)。

paste虽然适用于文件,而不是字符串,但在 Bash 中,这很容易解决;只需使用流程替换

#!/bin/bash

# Refactored into a function for maintainability and legibility
# Maybe you want to factor out the magical constants 6 and 21 somehow as well?
atoms () {
    awk '# Simplified script; apparently, you simply want lines 6 through 21
     NR==6,NR==21 { print $1 }' "$@"
}
# Ditto
cols () {
    awk '# Simplified this script as well
     NR==6,NR==21 {
       printf  "%13.8f\t%12.8f\t%12.8f%s%s%s%s%4.3f\n", $2, $3, $4,
               "     XXXX", " 1", "    xx","  " $1"  ", "  0.000"}' "$@"
}

paste <(atoms "$carf") <(cols "$coor")

如果文件很大,在第 21 行之后退出可以节省大量时间。

NR==22 { exit }
于 2012-07-31T07:39:02.050 回答
1

对于每个文件的每一行,您的 AWK 脚本从 6 计数到 21 。我不认为这是必要的。我认为您要做的只是测试行号是否在该范围内。这是我的意思的一个例子:

FC=$(awk 'NR >= 6 && NR <=21)
     print $1}' $carf)

但是,您真正需要做的是结合两个 AWK 脚本,将第一个文件中的值保存在数组中,并在打印第二个文件中的值时打印数组中的值。

awk 'FNR == NR && FNR >= 6 && FNR <= 21 {    # first file
        carf[FNR] = $1
     }
     FNR == NR {
         next
     }
     FNR >= 6 && FNR <= 21 {    # second file
         printf  "%-4s%13.8f\t%12.8f\t%12.8f%s%s%s%s%4.3f\n", carf[FNR], $2, $3, $4,
             "     XXXX", " 1", "    xx","  " $1"  ", "  0.000"
     }' "$carf" "$coor"

请注意,没有echo(或paste)。

除非您在输出中确实需要制表符,否则您可以将它们排除在外并调整字段宽度以提供所需的输出对齐方式。

于 2012-07-31T07:58:14.087 回答