簡體   English   中英

grep / awk stdin有局限性嗎?

[英]grep/awk stdin Limitations?

我環顧四周,但找不到任何已回答此問題的人。

我正在編寫一個bash腳本,該腳本將讀取6個不同的csv文件,並計算所有文件中的多少行在一起中具有某些標記。

(這是一個聯系人列表數據庫,並且有用於公司或私人電子郵件地址的標簽)

這是我編寫的代碼示例:

### First Scan - Business emails ###

bus="$(awk 'BEGIN {FS = ","}{print $27}' FILE*full* | grep -c "Business")"

echo "No. of Business Accounts: $bus"

### Second Scan - Private emails ###

priv="$(awk 'BEGIN {FS = ","}{print $27}' FILE*full* | grep -c "Private")"

echo "No. of Private Accounts: $priv"

腳本返回的值看起來非常正確。 然而! 我知道一個事實,即每個文件中的每一行在同一位置都具有標記“ business”或“ private”-並且沒有空行,但是當我將兩個結果加在一起時,它並不等於行的總數...大約有45000人失蹤...

grepawkstdin是否有任何限制-完整的數據庫長度超過200萬行...

請幫忙! :-)

最有可能的是,在數百萬的csv行中,有一些包含帶引號的字段,並帶有逗號。 Awk對報價一無所知。 它只會以逗號分隔。

如果使用的是Gnu awk,則可以使用FPAT變量,該變量使您可以為字段指定正則表達式,而不是為字段分隔符指定正則表達式。 例如,這將適用於許多CSV文件(除了csv文件使用CR-LF行尾的行尾問題之外)。 -v var=value大致等效於BEGIN{var="value"} ,而不僅僅是Gnu awk。)

gawk -v FPAT='[^",][^,]*|("[^"]*")*'  

順便說一句,不需要使用grepawk 您可以使用awk進行過濾和計數; 實際上,您可以在同一掃描中進行兩項計數:

gawk -v FPAT='[^",][^,]*|("[^"]*")*' '
     $27 ~ /Business/ {++bus}
     $27 ~ /Private/  {++pri}
     END { print "No. of Business accounts", bus
           print "No. of Private accounts", pri}' FILE*full* 

上面的正則表達式非常簡單,並且不會處理“不正確”的CSV文件(如果您可以將該單詞用於這種寬松定義的格式)。 它匹配:

[^",][^,]*|("[^"]*")*
  |    |  | |  |  | |
  +----+--+-+--+--+-+----- A character other than quote or comma
       |  | |  |  | |
       +--+-+--+--+-+----- Followed by any number of characters other than comma
          | |  |  | |
          +-+--+--+-+--- OR
            |  |  | |
            |  |  | +----- Any number of sequences consisting of
            |  |  |
            +--+--+--------- A quote
               |  |
               +--+--------- Any number of characters other than a quote
                  |
                  +--------- Another quote

因此,第一個選擇將匹配未加引號的字段,例如93.7Private ,第二個選擇將匹配:

  • 引用的字段,可能包括逗號: "Blood, sweat and tears"

  • 帶引號的字段按照引號加倍規則: """My goodness,"" she said" (請參閱RFC 4180的 2.7節。)

它不會嘗試匹配不包含在標准中的反斜杠轉義的引號(也不由MS Excel,afaik生成),並且如果帶引號的字段錯誤地包含未雙引號,則它將完全失敗。

您可以在上面的程序上使用一個簡單的變體來查看未正確解析的行,這可能使您可以修復它們或改編正則表達式,例如:

gawk -v FPAT='[^",][^,]*|("[^"]*")*' '
     $27 !~ /Business/ && $27 !~ /Private/ {
           print "----"
           print "Error at line " NR:
           print $0
           for (i=1; i<=NF; ++i) printf "%2d: |%s|\n", i, $i
     }' filename

試試這個,告訴我們您得到什么輸出:

awk -F',' '
$27 ~ /Business/ { bus++; next }
$27 ~ /Private/  { priv++; next }
{ other++; print "Non-Business/Private:", FILENAME, FNR, $27 }
END { print NR, bus, priv, other }
' FILE*full*

上面輸出中的NR代表總記錄,應等於bus + priv + other。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM