2012-07-31 64 views
1

好的,所以首先要解釋我更詳細的問題。我在這裏設置兩個變量;一個複製一列數據,另一個拷貝數據的多列...使用包含多列數據的變量回顯多個變量; bash

的問題是,我想數據的第一列追加盈方多列,同時保持它們對準

環當我將它們單獨重定向到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 ....... 
+0

你在尋找'paste'命令嗎? – tripleee 2012-07-31 07:18:55

+0

也許,不確定...我的回聲命令工作不正常...所以我只是需要一些將保持列對齊,而不是如圖所示 – Sloan 2012-07-31 07:24:31

+0

'for'循環顯示了一個明顯的誤解'awk'處理模型。你的代碼被讀取的每一行調用,從上到下;所以當'awk'處理第6行時,在整個腳本中'NR'將等於六,並且當讀取第7行時,整個腳本將再次以該值處理。 – tripleee 2012-07-31 17:12:43

回答

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)。

除非您確實需要在輸出中使用製表符,否則可以將它們排除並調整字段寬度以提供所需的輸出對齊。

+0

我從未使用FNR ......它究竟做了什麼?另外,當你在第二部分的printf中調用carf時,%-4s會做什麼? – Sloan 2012-07-31 15:06:05

+0

@Sloan:'FNR'是文件記錄號。它就像'NR',但是它在每個文件的開頭重置爲1。如我在答案中所做的那樣,對不同文件做不同的事情很有用。當'FNR == NR'時,你知道你在第一個文件中。 '%-4s'字段規範說「一個左對齊的4個字符的字符串字段」(連字符表示左對齊)。 – 2012-07-31 15:27:50

+0

啊,我想我現在明白了....恩,但我有一個小問題的代碼。它似乎只是從$ carf文件輸出,而不是從$ coor文件中做任何事情。 – Sloan 2012-07-31 16:46:25

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 }' "[email protected]" 
} 
# 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"}' "[email protected]" 
} 

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

如果文件很大,你可以通過行後退出節省了大量的時間21

NR==22 { exit } 
+0

所以...我不需要和如果語句?...我只能說NR == ##,NR == ##,這將帶我從一些開始行到另一行? – Sloan 2012-07-31 15:03:52

+0

是的,for循環特別浪費。該條件在技術上與「if」類​​似,但使用awk的內置行範圍選擇機制更爲優雅。 – tripleee 2012-07-31 16:20:09