Text-Processing

搜尋包含不匹配分隔符的行

  • August 22, 2021

執行pdflatex時崩潰,我的.aux文件包含如下行

\@writefile{toc}{\contentsline {section}{\numberline {B

我能想到的辨識此類行的唯一方法是計算 ’ 的數量是否{超過}任何行中 ’ 的數量。我希望能夠檢查.aux生成的文件pdflatex並確定它是否包含這樣的行。有沒有辦法使用 或其他實用程序來做到這grep一點awk?當然,如果有另一種更有效的方法來辨識這些線條,我會很高興。

感謝您的建議

這是另一個簡短的:

awk '{while(gsub(/{[^{}]*}/, "")){ }} /[{}]/ {exit 1}'

或者可能

awk '{x=$0;while(gsub(/{[^{}]*}/, "")){ }} /[{}]/ {print FILENAME,FNR,x;nextfile}'

這會刪除所有的平衡{...},如果仍然有{or}字元,則採取一些行動。

是的,在 grep(使用 PCRE)中是可能的(並且非常精確),但並不容易理解。

grep -Px '((?>[^{}]+|\{(?1)\})*)'

或者,我們可以定義輸入 ( $str) 和適當的正則表達式 ( $re):

$ printf '%s\n' "$str" | grep -vP "${re//[ $'\n']/}"

那是如何工作的?

當今的正則表達式可以匹配平衡的結構(不是大多數舊的正則表達式引擎)。

在 PCRE 中,遞歸是做到這一點的關鍵。

為了匹配一個平衡的集合,需要這個結構:

b(m|(?R))*e

b開始模式在哪裡({在你的情況下),

e結束模式在哪裡(在你的情況}下),

中間m模式在哪裡([^{}]+在你的情況下)。

{([^{}]*+|(?R))*}

正如在這裡所看到的那樣

但這是一個遞歸整個正則表達式 ( ) 的非錨定匹配?R

可以使用grep 選項獲得錨定版本(以匹配整行)。-x

允許大括號之外的其他文本的完整解決方案變得有點複雜,因此,使用 Perl 正則表達式的選項來忽略我們可以編寫的空格。並將正則表達式結構更改為(有點慢):

((m+|b(?1)e)*)

原來的結構b(m|(?R))*e

(?(DEFINE)(?'nonbrace'  [^{}\n]       ))  # Define a non-brace
(?(DEFINE)(?'begin'     {             ))  # Define the start text
(?(DEFINE)(?'end'       }             ))  # define the end text 
(?(DEFINE)(?'middle'    (?&nonbrace)  ))  # define the allowed text
                                         # inside the braces

(?(DEFINE)(?'nested'                            # define a nested
   ((?&begin)((?&middle)|(?&nested))*(?&end))  # pattern
 ))                                            # here

^((?&nonbrace)*+(?&nested))*+(?&nonbrace)*$     # finally, use this regex.

正如這裡測試的那樣。

或替代結構 ((m+|b(?1)e)*)

(?(DEFINE)(?'nonbrace'  [^{}\n]       ))  # Define a non-brace
(?(DEFINE)(?'begin'     \{            ))  # Define the start text
(?(DEFINE)(?'end'       \}            ))  # define the end text 
(?(DEFINE)(?'middle'    (?&nonbrace)  ))  # define the allowed text
                                         # inside the braces

(?(DEFINE)(?'nested'                             # define a nested
    (  (?&middle)++  |  (?&begin)(?&nested)(?&end)  )*
))

^(?&nested)$     # finally, use this regex.

如此處測試

請注意,一旦帶有許多 DEFINE 的非常長的正則表達式被正則表達式引擎編譯,它的工作速度與較短的正則表達式相同。

增加的功能是描述對人類來說更清晰(或者,至少,我希望如此)。

這顯示了對正則表達式的更清晰的描述,通常更易於人類理解,但使用了 PCRE 中相當深入的正則表達式特徵。

腳本

要將所有這些想法與 grep(GNU 和 PCRE)一起使用,請使用以下 shell (bash) 範例:

#!/bin/bash

str=$'
a
abc
{}
{a}
{{aa}}
{a{b}}
{a{bb}a}
{a{b{c}b}a}
n{a{}}nn{b{bb}}
\@writefile{toc}}}}{\\contentsline {section}{\\numberline {B
\@writefile{toc}{\contentsline {section}{\\numberline {B
Previous lines contain mismatched braces. This and the next line don\'t.
\@writefile{toc}{\\contentsline {section}{\\numberline {B}}}
'

re=$'                    
 (?(DEFINE)(?\'nonbrace\'  [^{}\\n]      ))
 (?(DEFINE)(?\'begin\'     {             ))
 (?(DEFINE)(?\'end\'       }             ))
 (?(DEFINE)(?\'middle\'    (?&nonbrace)  ))
 (?(DEFINE)(?\'nested\'
     ((?&begin)((?&middle)|(?&nested))*(?&end))
   ))
 ^((?&nonbrace)*(?&nested))*(?&nonbrace)*$
'

printf '%s\n' "$str" | grep -P "${re//[ $'\n']/}"

a
abc
{}
{a}
{{aa}}
{a{b}}
{a{bb}a}
{a{b{c}b}a}
n{a{}}nn{b{bb}}
Previous lines contain mismatched braces. This and the next line don't.
\@writefile{toc}{\contentsline {section}{\numberline {B}}}

試驗結果

最後,要讓所有不匹配的行反轉輸出-v(如果您需要在執行的 shell 中執行以下內容,請參考上面的腳本):

$ printf '%s\n' "$str" | grep -vP "${re//[ $'\n']/}"

\@writefile{toc}}}}{\contentsline {section}{\numberline {B
\@writefile{toc}{ntentsline {section}{\numberline {B

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