簡體   English   中英

awk:致命:設置多個字段分隔符時正則表達式無效

[英]awk: fatal: Invalid regular expression when setting multiple field separators

我試圖解決Grep regex使用awk只選擇 10 個字符 問題包含在字符串XXXXXX[YYYYY--ZZZZZ ,OP 想要在文本中唯一的[--字符串之間打印文本。

如果它只是一個-我會說使用[-[]作為字段分隔符(FS)。 這將 FS 設置為-[

$ echo "XXXXXXX[YYYYY-ZZZZ" | awk -F[-[] '{print $2}'
YYYYY

棘手的一點是[作為字符類也有特殊含義,因此為了使其正確解釋為可能的 FS 之一,它不能寫在第一個位置。 嗯,這是通過說[-[]來完成的。 所以我們已經完成匹配-[

但是,在這種情況下,它不是一個而是兩個連字符:我想說--[ 我不能說[--[]因為連字符也有定義范圍的含義。

我能做的是使用-F"one pattern|another pattern"例如:

$ echo "XXXXXXXaaYYYYYbbZZZZ" | awk -F"aa|bb" '{print $2}'
YYYYY

因此,如果我嘗試將其與--[一起使用,則無法獲得正確的結果:

$ echo "XXXXXXX[YYYYY--ZZZZ" | awk -F"--|[" '{print $2}'
awk: fatal: Invalid regular expression: /--|[/

事實上,甚至沒有[作為術語之一:

$ echo "XXXXXXX[YYYYYbbZZZZ" | awk -F"bb|[" '{print $2}'
awk: fatal: Invalid regular expression: /bb|[/

$ echo "XXXXXXX[YYYYYbbZZZZ" | awk -F"bb|\[" '{print $2}'
awk: warning: escape sequence `\[' treated as plain `['
awk: fatal: Invalid regular expression: /bb|[/

$ echo "XXXXXXX[YYYYYbbZZZZ" | awk -F"(bb|\[)" '{print $2}'
awk: warning: escape sequence `\[' treated as plain `['
awk: fatal: Unmatched [ or [^: /(bb|[)/

你看我試圖轉義[ ,用括號括起來,但沒有任何效果。

那么:我該怎么做才能將字段分隔符設置為--[ 有可能嗎?

恕我直言,如果我們從查看 split() 命令使用的正則表達式開始,這是最好的解釋,因為它明確顯示了使用文字與動態正則表達式將字符串拆分為字段時發生的情況,然后我們可以將其與字段分隔符相關聯.

這使用文字正則表達式(由/ s 分隔):

$ echo "XXXXXXX[YYYYY--ZZZZ" | awk '{split($0,f,/\[|--/); print f[2]}'
YYYYY

因此需要[被轉義,所以它是字面意思,因為[是一個正則表達式元字符。

這些使用動態正則表達式(一個存儲為字符串):

$ echo "XXXXXXX[YYYYY--ZZZZ" | awk '{split($0,f,"\\[|--"); print f[2]}'
YYYYY

$ echo "XXXXXXX[YYYYY--ZZZZ" | awk 'BEGIN{re="\\[|--"} {split($0,f,re); print f[2]}'
YYYYY

$ echo "XXXXXXX[YYYYY--ZZZZ" | awk -v re='\\[|--' '{split($0,f,re); print f[2]}'
YYYYY

因此需要[轉義 2 次,因為 awk 必須將包含正則表達式的字符串(在最后兩個示例中名為re的變量)轉換為正則表達式(使用一個反斜杠),然后才能將其用作拆分中的分隔符() 調用(用完第二個反斜杠)。

這個:

$ echo "XXXXXXX[YYYYY--ZZZZ" | awk -v re="\\\[|--" '{split($0,f,re); print f[2]}'
YYYYY

將變量內容暴露給 shell 以進行評估,因此需要[轉義 3 次,因為 shell 首先解析字符串以嘗試擴展 shell 變量等(使用一個反斜杠),然后 awk 必須轉換字符串在將正則表達式用作 split() 調用中的分隔符(用完第三個反斜杠)之前,將其保存為正則表達式(用完第二個反斜杠)。

字段分隔符只是一個存儲為名為 FS 的變量(如上面的re )的正則表達式,具有一些額外的語義,因此上述所有內容都適用於它,因此:

$ echo "XXXXXXX[YYYYY--ZZZZ" | awk -F '\\[|--' '{print $2}'
YYYYY

$ echo "XXXXXXX[YYYYY--ZZZZ" | awk -F "\\\[|--" '{print $2}'
YYYYY

請注意,我們可以使用方括號表達式而不是將其轉義以按字面意思處理[

$ echo "XXXXXXX[YYYYY--ZZZZ" | awk '{split($0,f,/[[]|--/); print f[2]}'
YYYYY

然后我們不必擔心在我們添加解析層時逃避轉義:

$ echo "XXXXXXX[YYYYY--ZZZZ" | awk -F "[[]|--" '{print $2}'
YYYYY

$ echo "XXXXXXX[YYYYY--ZZZZ" | awk -F '[[]|--' '{print $2}'
YYYYY

您需要使用雙反斜杠來轉義雙引號字符串中的正則表達式元字符,以便將其視為正則表達式元字符,否則(如果您使用單反斜杠)它將被視為轉義序列。

$ echo 'XXXXXXX[YYYYYbbZZZZ' | awk -v FS="bb|\\[" '{print $2}'
YYYYY

這與 GNU Awk 3.1.7

echo "XXXXXXX[YYYYY--ZZZZ" | awk -F"--|[[]" '{print $2}'    
echo "XXXXXXX[YYYYYbbZZZZ" | awk -F"bb|[[]" '{print $2}'

暫無
暫無

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

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