2016-07-29 35 views
3

分開的不同值我有一個UNIX文件Err_Call_sipregtracking.csv如下獲取逗號在UNIX

colnum~filename~date~fieldnum~name~value 
15~YYYYMMDD_BDACA_SELFRELATIVE_ARN~30MAR2016:00:00:00~1~BDA_CA_Code~1 
15~YYYYMMDD_BDACA_SELFRELATIVE_ARN~30MAR2016:00:00:00~2~ARN_Code~2 
15~YYYYMMDD_BDACA_SELFRELATIVE_ARN~30MAR2016:00:00:00~544~ALL~0 
15~YYYYMMDD_BDACA_SELFRELATIVE_ARN~30MAR2016:00:00:00~544~ALL~0 

這裏定界符~。 我想的名字列的不同值到一個變量

我所需的輸出是:

'BDA_CA_Code','ARN_Code','ALL' 

請幫我實現this.I試圖用這種

cat Err_Call_sipregtracking.csv | awk -F'~' '{print $5}' | uniq 

輸出是:

name 
BDA_CA_Code 
ARN_Code 
ALL 

但我不想在結果頭,我也希望他們在現狀tes和逗號分隔。

+0

note'cat file | awk'things''沒有必要。 awk'東西'文件就足夠了。 – fedorqui

回答

1

這可能不是很優化,但工作原理:

tail -n+2 Newfile.csv | awk -F'~' '{$5="\""$5"\""; print $5}' | uniq | tr '\n' ',' | sed 's/\,$/\n/' 

如果你想單引號代替:

tail -n+2 Newfile.csv | awk -F'~' '{a = "'"'"'"; print a $5 a}' | uniq | tr '\n' ',' | sed 's/\,$/\n/' 

說明:

  • tail -n+2 Newfile.csv省略了第一線
  • awk -F'~' '{$5="\""$5"\""; print $5}'提取第五柱,並用引號包圍它(對於單引號,注意如何不必要的複雜報價打印,可能有辦法解決)
  • uniq刪除重複
  • tr '\n' ','替換逗號換行符
  • sed 's/\,$/\n/'刪除最後一個逗號和一個換行符替換它(輸出可讀性)
+3

這很有趣;但是,請注意'awk'可以在內部處理大部分內容。一般來說,管道這麼多的命令不被認爲是好的做法,因爲它涉及更多的CPU時間。 – fedorqui

+2

這是真的;然而,我發現管路是一步一步解釋的,除此之外,這些命令遠遠超出了'awk'和文本處理的範圍,對於大多數用途來說,CPU在這裏應該不是什麼大問題。這就是說,我明白你的觀點。 – pie3636

+2

是的,我認爲這是一個平衡的問題,事實上,小命令的好處在於只做一件事情。我當前的答案有點過於複雜,因爲我只想使用awk。然而,在你的回答中,例如,第一個管道可以通過將一個物品放置在一個數組中,通過簡單的'NR> 1'和'uniq'來移除。 – fedorqui

4

這裏的關鍵是將值存儲在一個數組,所以你然後打印所有元素:

$ awk -F'~' 'NR>1{item[$5]} END {for (i in item) print i}' file 
ARN_Code 
BDA_CA_Code 
ALL 

注意NR>1使用跳過頭。

然後,您可以打印包裹着單引號與printf "\047%s\047\n", i的元素,因爲print "\047hello\047"打印'hello'

$ awk -F'~' 'NR>1{item[$5]} END {for (i in item) printf "\047%s\047\n", i}' file 
'ARN_Code' 
'BDA_CA_Code' 
'ALL' 

要加入這些到逗號分隔的項目列表,只是每一個項目之前打印一個逗號開始從第二個(credits to Ed Morton):

for (i in item) printf "%s\047%s\047", (++c>1 ? "," : ""), i 
print "" 

參見實例:

$ awk -F'~' 'NR>1{item[$5]} END {for (i in item) printf "%s\047%s\047", (++c>1 ? "," : ""), i; print ""}' file 
'ARN_Code','BDA_CA_Code','ALL' 
+0

'awk'裏的'for'循環可以避免.. – sjsam

+0

@sjsam怎麼樣?我看不到。 – fedorqui

+0

您可能已經通過我的回答,但我覺得單個for-loop在這裏更具可讀性。節省時間。和一個++用於解決問題 – sjsam

3

awk是你的朋友:

$ var=$(awk -v FS="~" 'NR>1 && !($5 in field){printf "\047%s\047,",$5;field[$5]}' Err_Call_sipregtracking.csv) 
$ var="${var%,}" #Stripping the trailing comma 
$ echo "$var" 
'BDA_CA_Code','ARN_Code','ALL' 

注意

+0

我喜歡用'-vq =''「'來打印這些單引號。它看起來更容易閱讀。 – fedorqui

+0

@ fedoroqui--我是unix的新手。這個工作很好,但我無法理解它是如何實現的。請您解釋一下printf語句中的內容 –

+1

1)在'-v'和變量名之間不留空格該腳本不必要地特定於gawk。 2)測試獨特性的慣用方式是一個名爲/填充爲'!seen [$ 5] ++'的數組。 3)沒有終止的換行符,輸出不是每個POSIX的文本,因此在之後解析它的時候會引入未定義的行爲。 4)不要添加東西,然後再將它們帶走(例如逗號),因爲它容易出錯。 5)您不需要執行shell操作來更改awk輸出,只需將其保存在awk中即可。 6)要在awk腳本中獲得單引號,使用八進制'\ 047' - 遠不止一個變量。 –

0

您可以跳過第一行以sed 1d,與cut獲得第5場,並使用printf爲marmatting獨特的排序結果:

printf "'%s'\n" $(sed 1d Err_Call_sipregtracking.csv | cut -d~ -f5 | sort -u) 

這不能滿足你的要求把它作爲一個單行:

printf "'%s'," $(sed 1d Err_Call_sipregtracking.csv | cut -d~ -f5 | sort -u)|sed 's/,$//' 
3
$ awk -F'~' 'NR>1 && !seen[$5]++{printf "%s\047%s\047", (NR>2 ? "," : ""), $5} END{print ""}' file 
'BDA_CA_Code','ARN_Code','ALL' 
0

你的命令是正確的,但稍作修改,如下圖所示:

cat Err_Call_sipregtracking| awk -F'~' '{print $5}' | uniq|sed 1d | sed -n -e 'H;${x;s/\n/,/g;s/^,//;p;}'