2012-09-13 135 views
3

我有一個CSV文件,這當然是逗號分隔的,你想刪除所有具有例如特定標題列特定標題的所有列:如何刪除包含使用AWK

voltage, current, power, voltage, current, power 
     2,  3,  6,  12,  12, 144 
     3,  5, 15,  10,  10, 100 

應該

voltage, power, voltage, power 
     2,  6,  12, 144 
     3, 15,  10, 100 
+0

是你想刪除的標題固定總是「當前」或可能是什麼? – Kent

回答

2

script.awk內容:中file.txt

BEGIN { 
    FS=" , " 
} 

NR==1 { 
    for (i=1; i<=NF; i++) { 
     if ($i == "current") { 
      array[i]++ 
     } 
     else { 
      printf (i != NF) ? $i", " : $i 
     } 
    } 
} 

NR>=2 { 
    for (j=1; j<=NF; j++) { 
     if (!(j in array)) { 
      printf (j != NF) ? $j", " : $j 
     } 
    } 
} 

{ 
    printf "\n" 
} 

內容:

voltage , current , power , voltage , current , power 
2 , 3 , 6 , 12 , 12 , 144 
3 , 5 , 15 , 10 , 10 , 100 

運行,如:

awk -f script.awk file.txt 

結果:

voltage, power, voltage, power 
2, 6, 12, 144 
3, 15, 10, 100 
+0

我不知道什麼是錯,但是這給了我與輸入文件相同的輸出 –

+0

@FERY:你是否在我描述的輸入文件上測試了這個?你使用的是什麼版本的awk? – Steve

+0

@FERY:我應該說你的分隔符在你描述的輸入文件中是不一致的。我假設你的輸入被分隔爲:'「,」'。如有必要,請在BEGIN塊中更改'FS'的值。 – Steve

0

假設輸入文件名是input.txt中

awk -F ',' '{print $1 "," $3 "," $5 "," $6 }' input.txt 
+0

事情是列數太高(2500),所以我需要一個循環遍歷所有列 –

0

注意,一般CSV文件處理,應該使用適當的庫。如果數據非常簡單,即沒有嵌入逗號,換行符等,可以使用更簡單的工具。

你必須從史蒂夫一個很好的解決方案awk所以我會添加基於的coreutils和grep答案:

# find columns to remove 
pattern=current 
cols=$(head -n1 a.csv | tr ',' '\n' | grep -n "$pattern" | cut -d: -f1 | paste -s -d,) 

# remove all columns that matched 
cut --complement -d, -f$cols a.csv 

輸出:

voltage, power, voltage, power 
2 , 6 , 12 , 144 
3 , 15 , 10 , 100 

注意,--complement選項是GNU縮減擴展。爲了產生$cols其他削減,這樣的事情應該做的(在zsh中在FreeBSD上測試過):

# number of columns 
file=a.csv 
pattern=current 
n=$(head -n1 "$file" | tr ',' '\n' | wc -l) 

# generate complementary list 
cols=$(jot $n \ 
| grep -xvFf <(head -n1 "$file" | tr ',' '\n' | grep -n "$pattern" | cut -d: -f1) \ 
| paste -s -d, -) 

# remove columns 
cut -d, -f$cols "$file" 
+0

我認爲問題的關鍵是有很多列要刪除,他們的位置不一定是固定的或以固定的時間間隔。 –

+0

更改爲coreutils解決方案。 – Thor

1
如果你想刪除與「當前」標題中的所有列

kent$ awk -F',' 'NR==1{for(x=1;x<=NF;x++)if($x!="current")l[x]++;}{for(i=1;i<=NF;i++)if(i in l)printf (i==NF)?$i"":$i", ";printf "\n"}' test.txt 

voltage, power, voltage, power 
2, 6, 12, 144 
3, 15, 10, 100 

注意:我刪除了上面test.txt中的空格。

  • 如果您有不同的標題需要刪除。你可以嘗試使用正則表達式,並將$x!="foo"替換爲正則表達式匹配。

  • 如果您知道刪除列的規則,例如第2列,第5,第8 ...(+ 3),則可以通過循環等方式進行處理。

+1

'l'(字母「l」)對於變量名來說是一個糟糕的選擇,因爲很難區分'1'(數字一)。此外,一些空間會增強可讀性。 –