2014-01-10 31 views
0

我具有以下輸入:grep的 - 正則表達式匹配的多個鍵 - 值對,並返回單線

TAG1 VALUE1;TAG2 VALUE2;sometext;TAG3 VALUE3;sometext;TAG4 VALUE4;TAG5 VALUE5;sometext 
TAG1 VALUE1;sometext;TAG3 VALUE3;sometext;TAG4 VALUE4;TAG5 VALUE5;sometext 
TAG1 VALUE1;TAG2 VALUE2;sometext;TAG3 VALUE3;sometext;TAG4 VALUE4;TAG5 VALUE5 
TAG1 VALUE1;TAG2 VALUE2;sometext;TAG3 VALUE3;sometext;TAG5 VALUE5;sometext 
TAG1 VALUE1;TAG2 VALUE2;sometext; 

我需要下面的輸出:

TAG2 VALUE2;TAG3 VALUE3;TAG5 VALUE5; 
TAG3 VALUE3;TAG5 VALUE5; 
TAG2 VALUE2;TAG3 VALUE3;TAG5 VALUE5; 
TAG2 VALUE2;TAG3 VALUE3;TAG5 VALUE5; 
TAG2 VALUE2; 

,或者如上述可替換地相同,但

grep -oP '(?<=TAG2).*?(?=;)|(?<=TAG3).*?(?=;)|(?<=TAG5).*?(?=;)' 
:只有

我試過下面的值

它的工作原理,但每一個值是在單獨的行:

VALUE2 
VALUE3 
VALUE5 

我不能假設所有線路將所有的標籤,所以我真的需要每個輸入的一行一行輸出。本地Linux工具首選 - sed,awk,grep等。

謝謝!

回答

1

這裏是一個Perl的方法:根據

$ perl -ne 'print $1," " while(/(?<=TAG[235])(.*?)(?=;)/g); print "\n";' in.txt 

編輯評論:

$ perl -ne 'print $1," " while(/(?<=(?:DEV|SRC|DST|ACT))(.*?)(?=;)/g); print "\n";' in.txt 

在行動:

$ cat in.txt 
TAG1 VALUE1;TAG2 VALUE2;sometext;TAG3 VALUE3;sometext;TAG4 VALUE4;TAG5 VALUE5;sometext 
TAG1 VALUE1;sometext;TAG3 VALUE3;sometext;TAG4 VALUE4;TAG5 VALUE5;sometext 
TAG1 VALUE1;TAG2 VALUE2;sometext;TAG3 VALUE3;sometext;TAG4 VALUE4;TAG5 VALUE5 
TAG1 VALUE1;TAG2 VALUE2;sometext;TAG3 VALUE3;sometext;TAG5 VALUE5;sometext 
TAG1 VALUE1;TAG2 VALUE2;sometext; 

$ perl -ne 'print $1," " while(/(?<=TAG[235])(.*?)(?=;)/g); print "\n";' in.txt 
VALUE2 VALUE3 VALUE5 
VALUE3 VALUE5 
VALUE2 VALUE3 
VALUE2 VALUE3 VALUE5 
VALUE2 
+0

這是不錯的,但在現實世界中的標籤是不是很相似(例如DEV,SRC,DST,ACT) - 你的模式可以更新爲在這種情況下工作嗎? – lubas

+0

+1好,我認爲PCRE在這裏會更好。 – anubhava

+0

@lubas:看看我的編輯,它適合你嗎? – Toto

2

隨着awk

$ awk 'BEGIN{FS=OFS=";"}{print $2, $4, $7}' file 
TAG2 VALUE2;TAG3 VALUE3;TAG5 VALUE5 
  • BEGIN{FS=OFS=";"}集的輸入和輸出字段分隔符作爲;
  • {print $2, $4, $7}根據該分隔符打印第2,第4和第7個字段。

我期待解析鍵/值對的原因是不是 不一定所有鍵都存在,而不一定在同一 列(但至少他們在特定的順序,如果目前,TAG1是 第一,TAG2未來等)

那麼這樣的事情應該讓:

awk -v values="TAG1 TAG5" 
     'BEGIN{split(values, vals, " ")} 
     {a[$1]=$2} 
     END{for (i in vals) print vals[i], a[vals[i]]}' 
    RS=";" file 
  • -v values="TAG1 TAG5" passwes awk值來分析。
  • 'BEGIN{split(values, vals, " ")}將它們存儲到vals[]陣列中。
  • {a[$1]=$2}保存a["TAG1"] = "VAL1"匹配。
  • END{for (i in vals) print vals[i], a[vals[i]]}'打印匹配。
  • RS=";"將記錄分隔符設置爲;,以便我們可以使用文件中的幾個值。

實例:

$ awk -v values="TAG1 TAG3" 'BEGIN{split(values, vals, " ")} {a[$1]=$2} END{for (i in vals) print vals[i], a[vals[i]]}' RS=";" file 
TAG1 VALUE1 
TAG3 VALUE3 
$ awk -v values="TAG1 TAG6" 'BEGIN{split(values, vals, " ")} {a[$1]=$2} END{for (i in vals) print vals[i], a[vals[i]]}' RS=";" file 
TAG1 VALUE1 
TAG6 
+0

我期待解析關鍵原因/值對不一定是所有的鍵都存在,並不一定在同一列(但至少他們是在特定的順序,如果存在的話,TAG1是第一個,TAG2下一個等...) – lubas

+0

@lubas用更廣泛的方法看到我更新的答案。 – fedorqui

+0

在27k線長的輸入端上僅響應2行(第一行中的TAG1 VALUE1和第二行中的TAG2 VALUE2)。 – lubas

0

使用純BASH:

l='TAG1 VALUE1;TAG2 VALUE2;sometext;TAG3 VALUE3;sometext;TAG4 VALUE4;TAG5 VALUE5;sometext' 
(IFS=';' && read -a arr <<< "$l"; echo "${arr[1]}; ${arr[3]}; ${arr[6]};") 
TAG2 VALUE2; TAG3 VALUE3; TAG5 VALUE5; 
  • IFS=';'使得定界符作爲;而讀取行成陣列。
+0

與awk相同 - 不能保證所有標籤的存在和特定位置 – lubas

+0

在這種情況下,我需要一些說明和更少的輸入/輸出示例。 – anubhava

+0

編輯的問題提供了更多的例子 – lubas