我需要計算以波形符 (~) 分隔的欄位的總和。我遇到的問題是我的資料也有分隔符號轉義。
例子
1~CEO~ashok\~kumar~1000
正如我們在上面的第三個欄位中所看到的,我們已經轉義了我想避免的分隔符號。我正在運行以下命令,但它無法處理此問題。
$ cat test.out|awk -F'~' 'BEGIN {sum=0} {sum+=$4} END{print sum}'
假設test.out
數據為:
1~CEO~ashok\~kumar~1000
2~CFO~Ranjan~2000
3~CEO~kumar~1000
所以我的輸出應該是 4000 但目前用我的指令我只得到 3000!
答案1
只需在處理之前將轉義分隔符號變更為其他內容即可awk
。這可以透過以下方式完成sed
:
$ cat test.out| sed 's/\\~/=/g' | \
awk -F'~' 'BEGIN {sum=0} {sum+=$4} END{print sum}'
4000
而且,正如通常的情況一樣,不需要cat
:
$ sed 's/\\~/=/g' test.out | awk -F'~' 'BEGIN {sum=0} {sum+=$4} END{print sum}'
答案2
這是不使用的替代方案awk
:
$ sed 's/\\~/=/g' test.out | cut -d"~" -f4 | paste -sd+ | bc
4000
上面的程式碼用於sed
交換\~
第三列中轉義的波形符。然後我們可以使用cut
選擇第四列數字,然後重建它們,以便它們之間用加號(+
)分隔。
$ sed 's/\\~/=/g' test.out | cut -d"~" -f4 | paste -sd+
1000+2000+1000
然後將該字串提供給二進制計算器,bc
對它們進行求和。
答案3
為了處理轉義,一般的方法是使用perl
or PCRE 及其交替正規表示式運算子與無回溯運算子結合。這裡是 GNU grep
:
grep -Po '(?>(?:\\.|.)*?~){3}\K(?:\\.|[^~])*' << \EOF
1~CEO~ashok\~kumar~1000
2~CFO~Ranjan~2000
3~CEO~kumar~1000
4~field2~field3\\~10000~field5-note-the-escaped-backslash-not-tilde
5~a\~b\~c\~no-4th-field-here
EOF
這使:
1000
2000
1000
10000
(您可以將其與平時相加awk '{s+=$0};END{print s}'
)。
使用 GNU sed
,您還可以這樣做:
sed -rn 's/((\\.|[^\~])*~){3}((\\.|[^~])*).*/\3/p'
使用 GNU awk
,您可以FPAT
將欄位定義為轉義字元或非波形符號或反斜線字元的序列:
awk -v FPAT='(\\\\.|[^\\\\~])*' '{print $4}'
答案4
這在 awk 中有點笨拙(除非您可以預處理原始程式碼來更改分隔符,但這需要知道另一個不能出現在輸入中的字元或字元序列)。您可以做的一件事是讀取整行,然後修改該行以獲取換行符號作為分隔符號(換行符是不可能出現在一行中的一件事)。
awk 'BEGIN {FS="\n"}
{
gsub("~", "\n");
gsub("\\\n", "~");
gsub("\\\\", "\\");
$0 = $0;
print $4;
}'