使用包含多列数据的变量回显多个变量;庆典

时间:2012-07-31 05:46:10

标签: bash awk

好的,首先要解释一下我所遇到的问题。我在这里设置两个变量;一个用于复制一列数据,另一个用于复制多列数据...

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

当我将它们单独重定向到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 .......

2 个答案:

答案 0 :(得分:2)

您正在寻找paste(1)命令。 echo无法将一个字符串拼接成另一个字符串(这看起来就像你要找的那样;在字符串2中的每一个新行之前,插入字符串1中的下一行)。

paste适用于文件,而不是字符串,但在Bash中,这很容易解决;只需使用process substitution

#!/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 }

答案 1 :(得分: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)。

除非您的输出中确实需要制表符,否则可以将它们保留并调整字段宽度,以便为您提供所需的输出对齐。