Bash

在命令行中刪除(可能是嵌套的)文本引號

  • March 3, 2019

我需要在命令行中解析大量文本並用空格替換所有(可能是嵌套的)文本引號。引號用特定的語法標記:[quote=username]quoted text[/quote].

帶有嵌套引號的範例輸入可能類似於:

text part 1 [quote=foo] outer quote 1 [quote=bar] inner quote [/quote] outer quote 2 [/quote] text part 2 [quote=foo-bar] next quote [/quote] text part 3

預期的輸出將是:

text part 1   text part 2   text part 3

在這個問題的幫助下,我得到了它以某種方式工作(上面得到了輸出),sed ':b; s/\[quote=[^]]*\][^[\/]*\[\/quote\]/ /g; t b'但中間部分([^[\/]] 是有問題的,因為引號可以包含像[or之類的字元]

話雖如此,如果輸入是例如,我的sed命令將不起作用。

text part 1 [quote=foo] outer quote 1 [quote=bar] inner quote [foo] [/quote] outer quote 2 [/quote] text part 2 [quote=foo-bar] next quote [/quote] text part 3

一個問題是它sed似乎不支持非貪婪限定符,因此總是從輸入中擷取最長可能的匹配。這使得通常難以處理**a)使用者名和b)**引用的文本。

我也猜想這sed不是解決這個問題的最佳工具,它甚至可能無法做這樣的事情。也許例如。perl或者awk可以更好地工作?

現在最後一個問題是,解決這個問題的最好和最有效的方法是什麼?

如果您知道輸入不包含<>字元,您可以這樣做:

sed '
 # replace opening quote with <
 s|\[quote=[^]]*\]|<|g
 # and closing quotes with >
 s|\[/quote\]|>|g
 :1
   # work our way from the inner quotes
   s|<[^<>]*>||g
 t1'

如果它可能包含<>字元,您可以使用以下方案對它們進行轉義:

sed '
 # escape < and > (and the escaping character _ itself)
 s/_/_u/g; s/</_l/g; s/>/_r/g

 <code-above>

 # undo escaping after the work has been done
 s/_r/>/g; s/_l/</g; s/_u/_/g'

使用perl遞歸正則表達式:

perl -pe 's@(\[quote=[^\]]*\](?:(?1)|.)*?\[/quote\])@@g'

甚至,正如您提到的:

perl -pe 's@(\[quote=.*?\](?:(?1)|.)*?\[/quote\])@@g'

使用,您可以通過添加選項perl來處理多行輸入。-0777使用sed,您需要在程式碼前面加上:

:0
$!{
 N;b0
}

以便將整個輸入載入到模式空間中。

引用自:https://unix.stackexchange.com/questions/503755