如何避免 Unix 指令中的轉義分隔符號?

如何避免 Unix 指令中的轉義分隔符號?

我需要計算以波形符 (~) 分隔的欄位的總和。我遇到的問題是我的資料也有分隔符號轉義。

例子

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

為了處理轉義,一般的方法是使用perlor 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;
}'

相關內容