2011-07-08 75 views

回答

5

是的,這可以很好地在AWK完成。沒有任何嚴重的黑客攻擊都很容易。

(這個例子工作在兩個The One True Awk和GAWK)。

{ 
    split($0, a, "\"") 
    $2 = a[2] 
    $3 = $(NF - 1) 
    $4 = $NF 
    print "and the fields are ", $1, "+", $2, "+", $3, "+", $4 
} 
+0

要格式化單行:'cat data.txt | awk'split($ 0,a,「\」「){$ 2 = a [2]} {$ 3 = $(NF-1)} {$ 4 = $ NF} {print」,字段爲「,$ 1,」+ 「,$ 2,」+「,$ 3,」+「,$ 4}'' –

+7

只有在第二個位置有單引號字段並且共有4個字段時纔有效。將接受在任何位置的任何引用字段將是理想的。 –

4

試試這個:

$ cat data.txt | awk -F\" '{print $2}' 
I am ABC 
I am not ABC 
+0

我要指出,這是不是特別的通用 - 它只是將字段分隔符更改爲'「並選擇第二個字段 –

+0

但是,如果我想在使用前後的信息...它不會工作=( –

+0

@羅伊陳 - 真,Awk是不是真的是正確的解析引用字符串的工具。回到第三篇文章[在這個可怕的格式化Google緩存鏈接](http://webcache.googleusercontent.com/search?q=cache:HA9Ix2yPEasJ:forums11.itrc.hp.com/service/forums/questionanswer.do% 3FthreadId%3D1028610 + awk + ​​quotes + field&cd = 1&hl = en&ct = clnk&gl = us&client = safari&source = www.google.com),您可以看到一個時間更長但可能有所幫助的示例。 –

0

好吧,如果你真的想所有三個字段,你可以讓他們,但它需要大量的管道:

$ cat data.txt | awk -F\" '{print $1 "," $2 "," $3}' | awk -F' ,' '{print $1 "," $2}' | awk -F', ' '{print $1 "," $2}' | awk -F, '{print $1 "," $2 "," $3}' 
ABC,I am ABC,35 
DEF,I am not ABC,42 

到最後管你有三個字段做任何你想用喜歡。

+0

其實,有4個字段。 – DigitalRoss

+0

哎呀 - 我錯過了原來的提交。 –

2

我揉成一團在一起重新分割$ 0改成叫B.雙引號之間的空間不作爲字段分隔陣列功能。可以與任意數量的字段一起使用,這些字段是引用引用和未引用引用的字段。這裏有:

#!/usr/bin/gawk -f 

# Resplit $0 into array B. Spaces between double quotes are not separators. 
# Single quotes not handled. No escaping of double quotes. 
function resplit(  a, l, i, j, b, k, BNF) # all are local variables 
{ 
    l=split($0, a, "\"") 
    BNF=0 
    delete B 
    for (i=1;i<=l;++i) 
    { 
    if (i % 2) 
    { 
     k=split(a[i], b) 
     for (j=1;j<=k;++j) 
     B[++BNF] = b[j] 
    } 
    else 
    { 
     B[++BNF] = "\""a[i]"\"" 
    } 
    } 
} 

{ 
    resplit() 

    for (i=1;i<=length(B);++i) 
    print i ": " B[i] 
} 

希望它有幫助。

2

對於這個問題的答案頂部僅適用於具有單引號場線。當我發現這個問題時,我需要一些可以用於任意數量的引用字段的東西。

最終我來到an answer by Wintermute in another thread,他提供了一個很好的通用解決了這個問題。我剛剛修改它以刪除引號。請注意,在運行以下程序時,需要使用-F\"調用awk。

BEGIN { OFS = "" } { 
    for (i = 1; i <= NF; i += 2) { 
     gsub(/[ \t]+/, ",", $i) 
    } 
    print 
} 

這個工程通過觀察數組中的所有其他元素將是引號內,當你在「字符數限制分離,所以它取代了空格分割的那些不與逗號報價。

,您可以很容易連鎖AWK做你需要的任何處理(只是再次使用字段分隔開關,-F,)的另一個實例

注意的是,如果第一場是引用這可能會打破 - 我沒有然後測試它,如果確實如此,應該很容易通過添加if語句來在2 rath開始如果該行的第一個字符是「」,則該值大於1。

0

這是什麼像什麼,我終於得到了工作就是爲我的項目更通用。 注意它不使用awk。

someText="ABC \"I am ABC\" 35 DESC '1 23' testing 456" 
putItemsInLines() { 
    local items="" 
    local firstItem="true" 
    while test $# -gt 0; do 
     if [ "$firstItem" == "true" ]; then 
      items="$1" 
      firstItem="false" 
     else 
      items="$items 
$1" 
     fi 
     shift 
    done 
    echo "$items" 
} 

count=0 
while read -r valueLine; do 
    echo "$count: $valueLine" 
    count=$(($count + 1)) 
done <<< "$(eval putItemsInLines $someText)" 

,其輸出:

0: ABC 
1: I am ABC 
2: 35 
3: DESC 
4: 1 23 
5: testing 
6: 456 
3

另一種方法是使用可變FPAT,限定了正則表達式描述每個字段的內容。

保存此AWK腳本parse.awk

#!/bin/awk -f 

BEGIN { 
    FPAT = "([^ ]+)|(\"[^\"]+\")" 
} 
{ 
    print $2 
} 

使其可執行與chmod +x ./parse.awk和分析你的數據文件作爲./parse.awk data.txt

"I am ABC" 
"I am not ABC" 
+0

謝謝你的正則表達式!;-)保存了我至少20分鐘的沮喪嘗試+1 – jweyrich

+0

這應該是被接受的答案。它像一個魅力,感謝。 – Nico

相關問題