2016-11-17 25 views
1

次のスクリプトは、bash:区切り文字付きの区切り文字で区切られているが、括弧で囲まれた文字列ではない場合は

は、私はそれがあるが、基本的には問題は、以下の入力で=ので、E値のように見えるとして出力されている理由は正確にはわからない:区切り文字を含む

avalue=one;bvalue=2.2.2.2;cvalue=3;dvalue=4.4.4;evalue=(HELLO:5;ABC:value=123.456); 

| awk ' { n=split($0,pcv,";") ; 

それは括弧内(発生した場合に区切るのではないために、区切り正規表現を修正する方法がある場合、私は思ったんだけど)、または前後の文字が5であっても、の、

I私はsedで入力文字列を変更してこれを行うことができますが、awkでそれを行うのが最善だと思います。

pcvtmp='avalue=one;bvalue=2.2.2.2;cvalue=3;dvalue=4.4.4;evalue=(HELLO:5;ABC:value=123.456); fvalue=five;gvalue=six;hvalue=7;ivalue=eight.8;jvalue=(HELLO:5;ABC:value2=onetwothree);kvalue=9999999;' 


     pcv=`echo $pcvtmp | awk ' { print $1 } ' \ 
         | awk ' { n=split($0,pcv,";") ; 
            for(i=1;i<n;i++){ 
            split(pcv[i],a1,"="); 
             #printf (" debug: \"%s\" | \"%s\",\n", a1[1], a1[2]); 
      if(a1[1]=="avalue")  {printf (" a\"avalue\": \"%s\",\n"  , a1[2]); continue } ; 
      if(a1[1]=="bvalue")  {printf (" b\"bvalue\": \"%s\",\n"  , a1[2]); continue } ; 
      if(a1[1]=="cvalue")  {printf (" c\"cvalue\": \"%s\",\n"  , a1[2]); continue } ; 
      if(a1[1]=="dvalue")  {printf (" d\"dvalue\": \"%s\",\n"  , a1[2]); continue } ; 
      if(a1[1]=="evalue")  {printf (" e\"evalue\": \"%s\",\n"  , a1[2]); continue } ; 
      if(a1[1]=="fvalue")  {printf (" f\"fvalue\": \"%s\",\n"  , a1[2]); continue } ; 
      if(a1[1]=="gvalue")  {printf (" g\"gvalue\": \"%s\",\n"  , a1[2]); continue } ; 
      if(a1[1]=="hvalue")  {printf (" h\"hvalue\": \"%s\",\n"  , a1[2]); continue } ; 
      if(a1[1]=="ivalue")  {printf (" i\"ivalue\": \"%s\",\n"  , a1[2]); continue } ; 
      if(a1[1]=="jvalue")  {printf (" j\"jvalue\": \"%s\",\n"  , a1[2]); continue } ; 
      if(a1[1]=="kvalue")  {printf (" k\"kvalue\": \"%s\",\n"  , a1[2]); continue } ; 
            } 
           } '` 

        echo "outof awk --" 
        echo "$pcv" 

電流出力にそれを:

# ./awk1.sh 
outof awk -- 
    a"avalue": "one", 
    b"bvalue": "2.2.2.2", 
    c"cvalue": "3", 
    d"dvalue": "4.4.4", 
    e"evalue": "(HELLO:5", 

期待出力

# ./awk1.sh 
outof awk -- 
    a"avalue": "one", 
    b"bvalue": "2.2.2.2", 
    c"cvalue": "3", 
    d"dvalue": "4.4.4", 
    e"evalue": "(HELLO:5;ABC:value=123.456)"  
    f"evalue": "five" 
    g"gvalue": "six" 
    h"hvalue": "7" 
    i"ivalue": "eight.8" 
    j"jvalue": "(HELLO:5;ABC:value2=onetwothree)" 
    k"kvalue" "9999999" 
+1

予想される出力は何ですか? – anubhava

+0

検証可能なサンプルi/pを提供し、o/p – Inian

+0

が期待される出力を編集に追加しました。見てくれてありがとう! –

答えて

3

無視してあなたは;に分割のため、このGNU awkコマンドを使用することができます;(...)内側:

pcvtmp='avalue=one;bvalue=2.2.2.2;cvalue=3;dvalue=4.4.4;evalue=(HELLO:5;ABC:value=123.456); fvalue=five;gvalue=six;hvalue=7;ivalue=eight.8;jvalue=(HELLO:5;ABC:value2=onetwothree);kvalue=9999999;' 

awk -v FPAT='[[:alnum:]_]+=(\\([^)]*\\)|[^;]+)' '{ 
    for (i=1; i<=NF; i++) { 
     sub(/=/, "\": \"", $i) 
     print substr($i, 1, 1) "\"" $i "\"" 
    } 
}' <<< "$pcvtmp" 

a"avalue": "one" 
b"bvalue": "2.2.2.2" 
c"cvalue": "3" 
d"dvalue": "4.4.4" 
e"evalue": "(HELLO:5;ABC:value=123.456)" 
f"fvalue": "five" 
g"gvalue": "six" 
h"hvalue": "7" 
i"ivalue": "eight.8" 
j"jvalue": "(HELLO:5;ABC:value2=onetwothree)" 
k"kvalue": "9999999" 

トリッキーな部分は、この正規表現とFPATを使用している:

[[:alnum:]_]+=(\\([^)]*\\)|[^;]+) 

key=value対のフィールドを形成します。ここでは、キーは1つ以上の単語の文字に続いて=であり、値は(...)または;以外です。

+1

ニース!'awk'の' FPAT'内部変数を知らない – Aserre

0

は、キー/ペアでの検索や、このサイトでぶらぶらして、最終的にこれを考え出した:これは正規表現として働く

https://regex101.com/r/NwCI3b/1

((?:\([^\)]*\)|[^=;])*)=((?:\([^\)]*\)|[^=;])*) 

又はこれ:

avalue=one;bvalue=2.2.2.2;cvalue=3;dvalue=4.4.4;evalue=(HELLO:5;ABC:value=123.456);fvalue=five;gvalue=six;hvalue=7;ivalue=eight.8;jvalue=(HELLO:5;ABC:value2=onetwothree);kvalue=9999999 
+1

標準のUNIXツールでregexpは動作しません。一部のオンラインツールがあるコンテキストで役に立つと思う正規表現を投稿することは、コンテキストなしでは役に立たない。 –

+1

あなたが正しいですね。私はそれをbashスクリプトの中から期待通りに解析することはできません。 –

+0

@TheHCD:これは最初にawkの問題として投稿したことを覚えています:) – anubhava

1

awk溶液:

$ cat sp.awk 

function key() { 
    match(line, /^[^=]+/) 
    tok = substr(line, 1, RLENGTH) 
    line = substr(line, RLENGTH + 1) 
} 

function eat(s) { 
    line = substr(line, length(s) + 1) 
} 

function val() { 
    if (match(line, /^\(.*\)/) || # try with brackets 
     match(line, /^[^;]+/)) { # try without brackets 
     tok = substr(line, 1, RLENGTH) 
     line = substr(line, RLENGTH + 1) 
    } else { 
     print "fail to read" | "cat 1>&2"; exit(1) 
    } 
} 

{ 
    line = $0 
    while (length(line)) { # `line' and `tok' are global 
     key(); k = tok 
     eat("=") 
     val(); v = tok 
     eat(";") 
     print k, v 
    } 
} 

使用:

テスト文字列が上記のようである

([^=,]*)=((?:\([^\)]*\)|[^=;])*) 

awk -f sp.awk file.txt 
関連する問題