2011-12-13 60 views
2

我有一些數據文件,我需要拉出一些信息。我想用單個awk腳本來獲取數據,所以我可以將一些數據吸收到bash數組中。awk腳本打印信息在特定的行

對於這一點,讓我們假設我需要以下的(1-索引): - 我需要AWK到上線2,3打印一列,和4 - 我需要AWK打印,2列1和3在第8行和以上。但是我希望所有的列都在列之前打印,而列之前的列是兩列。

使用下面的數據例如:

abc 
def 
ghi 
jkl 
mno 
1a1 
2b2 
11 22 33 44 
55 66 77 88 
99 00 12 13 
14 15 16 17 

我希望awk將打印字符串:

def ghi jkl 11 55 99 14 22 66 00 15 33 77 12 16 

我創建了以下,我認爲會的工作,但我得到一個錯誤說「END BOCK必須有一個動作部分」。

awk ' 
BEGIN {i=0;} 
{ 
    if ((NR >= 2) && (NR <= 4)) 
     print $1; 
    if (NR >= 8) 
    { 
     col1_arr[i] = $1; 
     col2_arr[i] = $2; 
     col3_arr[i] = $3; 
     i++; 
    } 
} 
END 
{ 
    for (j = 0; j < i; j++) 
     print col1_arr[j]; 
    for (j = 0; j < i; j++) 
     print col2_arr[j]; 
    for (j = 0; j < i; j++) 
     print col3_arr[j]; 
}' /path/to/my/file 

提前感謝。

+0

稍微繁瑣。但是,如果你想保持它的話,這很好。 END的代碼必須在END的同一行開始。 –

回答

2

這應該工作 -

awk ' 
BEGIN{i=0;} 
NR>=2 && NR<=4 {printf $1" "} 
NR >=8 {col1[i]=$1;col2[i]=$2;col3[i]=$3;i++;} 
END{for (i=0;i<=NR-8;i++) printf col1[i]" "; for(i=0;i<=NR-8;i++) printf col2[i]" ";for (i=0;i<=NR-8;i++) printf col3[i]" "}' INPUT_FILE 


[jaypal:~/Temp] cat data 
abc 
def 
ghi 
jkl 
mno 
1a1 
2b2 
11 22 33 44 
55 66 77 88 
99 00 12 13 
14 15 16 17 

[jaypal:~/Temp] awk ' 
BEGIN{i=0;} 
NR>=2 && NR<=4 {printf $1" "} 
NR >=8 {col1[i]=$1;col2[i]=$2;col3[i]=$3;i++;} 
END{for (i=0;i<=NR-8;i++) printf col1[i]" "; for(i=0;i<=NR-8;i++) printf col2[i]" ";for (i=0;i<=NR-8;i++) printf col3[i]" "}' data 
def ghi jkl 11 55 99 14 22 66 00 15 33 77 12 16 
+0

只是因爲我不夠了解,會使用像col1 [$ 1] = $ 1之類的東西導致重複數據只顯示一次?它會覆蓋自己嗎?我絕對不希望這樣的事情發生。 – jasonmclose

+0

使用col [$ 1] = $ 1,您將創建一個$ 1的索引並將$ 1的值分配給它。當在column1中有相同的值時,問題就會出現。這會導致索引被覆蓋。另外,你不會有正確的方式來獲得價值。這就是我更新答案的原因。訂單會變得混亂。 –

+0

剛編輯過的答案是使用'NR行號開始多個記錄',這樣你就不必硬編碼你必須彈出'for循環'的記錄數。 –

0
awk 'END { 
    printf "%s", (r OFS) 
    for (i = 0; ++i <= l;) 
    printf "%s", (m[i] (i < l ? OFS : RS)) 
    } 
NR > 1 && NR < 5 { 
    r = r ? r OFS $0 : $0 
    } 
NR >= 8 { 
    for (i = 0; ++i <= l;) 
    m[i] = i in m ? m[i] OFS $i : $i 
    }' l=3 infile 
+0

哦,男人。那是一些瘋狂的awk代碼。我甚至無法弄清楚發生了什麼。 – jasonmclose

1

下面的AWK行應該爲你做的工作:

awk '(NR==1 || NR>=5 && NR<=7){next;} 
{printf $1" ";if(NR>=8){two[NR]=$2;three[NR]=$3}} 
END{for(x in two)printf two[x]" ";for(x in three) printf three[x]" "}' yourFile 

測試你的榜樣:

kent$ echo "abc 
def 
ghi 
jkl 
mno 
1a1 
2b2 
11 22 33 44 
55 66 77 88 
99 00 12 13 
14 15 16 17 "| 
awk '(NR==1 || NR>=5 && NR<=7){next;} 
{printf $1" ";if(NR>=8){two[NR]=$2;three[NR]=$3}} 
END{for(x in two)printf two[x]" ";for(x in three) printf three[x]" "}' 

輸出

def ghi jkl 11 55 99 14 22 66 00 15 33 77 12 16 
+0

感謝您花時間在此工作。我從來沒有想過使用NR作爲索引。 – jasonmclose

2

略顯冗長。但是,如果你想保持它的話,這很好。

每個AWK規則是:

<Match> <Action> 

要麼可能是空的:

空<匹配>手段每一行匹配。
空<動作>表示打印(打印當前行)。

當然END沒有行,所以打印變得毫無意義。

你有什麼是:

END -- No Action -- 
--No Match -- { print your col arrays } 

你需要做的就是把行動放在同一行的到底是什麼。

END { 
for (j = 0; j < i; j++) 
    print col1_arr[j]; 
for (j = 0; j < i; j++) 
    print col2_arr[j]; 
for (j = 0; j < i; j++) 
    print col3_arr[j]; 
} 

您遇到的另一個問題是打印將新行放在打印的字符串上。
來解決這個使用printf("<format string>", variables);

BEGIN {i=0;} 
{ 
    if ((NR >= 2) && (NR <= 4)) 
     printf("%s ", $1); 
    if (NR >= 8) 
    { 
     col1_arr[i] = $1; 
     col2_arr[i] = $2; 
     col3_arr[i] = $3; 
     i++; 
    } 
} 
END { 
    for (j = 0; j < i; j++) 
     printf("%d ", col1_arr[j]); 
    for (j = 0; j < i; j++) 
     printf("%d ", col2_arr[j]); 
    for (j = 0; j < i; j++) 
     printf("%d ", col3_arr[j]); 
} 
+0

我們必須在所有'printf'語句中給出寬度,例如'printf(「%02d」,col1_arr [j]);'因爲在OP的數據中有一個值'00'。沒有它將不會有填充,並且值'00'將被彈出爲'0'。 –

+0

非常感謝您花時間向我解釋這一點。我很感激。 – jasonmclose