2017-10-09 74 views
-1

第1列的值我有一個這樣的製表符分隔文件:獨立的第2列分隔列表,將新行,繼承每新行

ID1 blue 
ID2 yellow,blue 
ID3 green,yellow,red 
ID4 red 
1D5 red,purple 

第二列,我需要分離出逗號列表,每個顏色在它自己的行上,並且對於每一個新行,我需要保留ID#。

我正在考慮使用sed來替換每個逗號用一個新行,但不知道如何添加關聯的ID返回。 Awk或perl?一番搜索後,我找不到答案...

最終結果將沒有逗號,看起來像這樣:

最終結果:

ID1 blue 
ID2 yellow 
ID2 blue 
ID3 green 
ID3 yellow 
ID3 red 
ID4 red 
1D5 red 
1D5 purple 

任何幫助,非常感謝。 此問題與Bash turning single comma-separated column into multi-line string非常相似,但我的第1列總是單個值,而類似的問題有多個值,第1列用逗號分隔。我無法通過查看類似問題找到我的解決方案。希望這個問題足以讓人留在這個網站上,並希望能夠幫助其他人。

回答

1
$ awk -F'[\t,]' '{for (i=2;i<=NF;i++) print $1, $i}' file 
ID1 blue 
ID2 yellow 
ID2 blue 
ID3 green 
ID3 yellow 
ID3 red 
ID4 red 
1D5 red 
1D5 purple 
+1

非常感謝,埃德! – Cath

0

這個簡單awk程序應該這樣做:

$ awk -F'\t' '{ n=split($2,arr,","); for(i=1;i<=n;i++) print $1,arr[i] }' file 
ID1 blue 
ID2 yellow 
ID2 blue 
ID3 green 
ID3 yellow 
ID3 red 
ID4 red 
1D5 red 
1D5 purple 

我們分割線到字段上標籤(\t),然後對每一行的逗號(,)與split()分裂的第二個字段。最後,我們遍歷數組arr中的所有元素,並按照(第一個字段,數組元素)對打印一行。

0

你的問題被標記了各種實用程序/膠水語言,包括Perl,所以這個答案描述了使用Perl編程語言的解決方案。

這裏是一個Perl單行溶液:

perl -lF/\\t/ -e 'print "$F[0] $_" for split /,/, $F[1]' test.txt 

鑑於製表符分隔的文件如本產生以下輸出的問題描述:

ID1 blue 
ID2 yellow 
ID2 blue 
ID3 green 
ID3 yellow 
ID3 red 
ID4 red 
1D5 red 
1D5 purple 

這工作大致與以下內容相同完整Perl腳本:

while (<>) { 
    chomp; 
    next unless length; 
    my ($id, $colors) = split /\t/, $_; 
    print "$id $_\n" foreach split /,/, $colors; 
} 

在這些解決方案中,我使用\t在選項卡上分割,儘管您提供的示例數據似乎不是以空格分隔的,而是專門用於製表符分隔。如果您的數據實際上只是「空白」分隔符,請將\t更改爲\s+

下面是一行代碼是如何工作的:

-l臺自動格格輸入和自動換行輸出。 -F切換隱式設置-a(意思是自動分割爲@F)和-n(這意味着迭代在命令行上傳遞的輸入文件)。

-F/\\t/表示在/\t/正則表達式上自動分割,換句話說,在製表符上填充@F並結果。 (如果您的數據更普遍空格分隔你可以改變\\t\\s+

因此,對於輸入的每一行,$F[0]將包含IDx領域,$F[1]將包含顏色,如yellow,blue

-e命令行開關意味着評估以下代碼,並且因爲我們有-n隱含在-F中,所以我們迭代該文件並在輸入文件的每行執行一次代碼。

而我們在通過代碼是:

print "$F[0] $_" foreach split /,/, $F[1] 

這意味着每文件的行,在顏色列表中的每個項,打印隨後顏色的ID(存儲在$F[0])(存儲在$_)。

我們通過拆分$F[1],其中可能包含yellow,blue上逗號,併爲每種顏色(使用foreach環)填充$_單獨導出的顏色。

描述腳本版本:

while(<>) {...}讀取在通過命令行(或從STDIN)上設置的文件一次一行,並且對於每個線填充$_

相關文章:

的Perl附帶perldoc命令,可以用一塊Perl的文檔閱讀的名字被調用的每一個完整的安裝。

請參閱以下內容:

  • perldoc perlrun - Perl的命令行開關的說明。
  • perldoc perlintro - Perl簡介。
  • perldoc perlre - 深入的Perl正則表達式概述。
  • perldoc -f split - 解釋Perl的split函數的工作原理。
  • perldoc perlsyn - 描述Perl的控制結構,如foreach循環。
  • perldoc perlop - Perl操作員的概述,包括<>

此外,如果你的數據是複雜得多所示,使用結構,如報價和分隔符的逃避,你應該更喜歡解析TSV/CSV文件中Text::CSV CPAN模塊。

+0

感謝您對所有的細節,戴維! – Cath

0

這可能爲你工作(GNU SED):

sed -r 's/^((\S+\s+)[^,]+),/\1\n\2/;P;D' file 

一個換行符其次密鑰及其空白(標籤)替換每個,

0

以下awk也可能幫助你。

awk '{gsub(/,/,RS $1"&");gsub(/,/," ")} 1' Input_file 

說明:

GSUB(/,/,RS $ 1" &「):使用awk的全球替代工具來替代在一條線上每個逗號與RS(新行)$ 1(該行的第一個字段)「&」表示逗號在這裏(表示我們提到要替換的變量/正則表達式)。

GSUB(/,/,」「):再次使用全球替代工具來awk,所以上述gsub會讓INPUT_FILE看起來如下。

ID1 blue 
ID2 yellow 
ID2,blue 
ID3 green 
ID3,yellow 
ID3,red 
ID4 red 
1D5 red 
1D5,purple 

這不是我們OP的輸出,所以再次全局地用簡單的空格替換逗號,所以得到正確的輸出如下。

ID1 blue 
ID2 yellow 
ID2 blue 
ID3 green 
ID3 yellow 
ID3 red 
ID4 red 
1D5 red 
1D5 purple 
+1

謝謝你,Ravinder! – Cath

+0

@Cath,歡迎你,很高興它幫助你。看到這個https://stackoverflow.com/help/someone-answers享受學習和分享知識,歡呼:) – RavinderSingh13

相關問題