실행할 때 충돌이 발생 pdflatex
하고 내 .aux
파일에 다음과 같은 줄이 포함되어 있습니다.
\@writefile{toc}{\contentsline {section}{\numberline {B
그러한 행을 식별하기 위해 제가 생각할 수 있는 유일한 방법은 숫자가 행의 숫자를 초과하는지 계산하는 것입니다 {
. 생성된 파일을 검사 하고 해당 줄이 포함되어 있는지 확인 }
하고 싶습니다 . 또는 다른 유틸리티를 사용하여 이를 수행할 수 있는 방법이 있습니까 ? 물론 이러한 선을 식별하는 보다 효율적인 대안이 있다면 기쁠 것입니다..aux
pdflatex
grep
awk
어떤 제안이라도 보내주셔서 감사합니다
답변1
또 다른 짧은 내용은 다음과 같습니다.
awk '{while(gsub(/{[^{}]*}/, "")){ }} /[{}]/ {exit 1}'
아니면 어쩌면
awk '{x=$0;while(gsub(/{[^{}]*}/, "")){ }} /[{}]/ {print FILENAME,FNR,x;nextfile}'
그러면 균형 잡힌 모든 항목이 제거되고 또는 문자가 여전히 존재하는 {...}
경우 일부 조치가 취해집니다 .{
}
답변2
예, 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)에서 이러한 모든 아이디어를 사용하려면 다음 쉘(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
(실행 중인 셸에서 다음을 실행해야 하는 경우 위의 스크립트를 가져옵니다).
$ printf '%s\n' "$str" | grep -vP "${re//[ $'\n']/}"
\@writefile{toc}}}}{\contentsline {section}{\numberline {B
\@writefile{toc}{ntentsline {section}{\numberline {B
답변3
sed
@rowboat 메소드 번역 awk
:
sed 'h; s/[^{}]//g; :1
s/{}//g; t1
/./!d; g'
그건:
sed '
h; # save a copy of the line on the hold space
s/[^{}]//g; # remove all characters but { and }
:1
s/{}//g; # remove the {}s (so starting with inner ones)
# and loop until there's no more {} to remove
t1
/./!d; # if the pattern space does not contain any single
# character, that means all {} were matched. Delete
g; # otherwise retrieve the saved copy which will be printed
# at the end of the cycle'
이는 POSIX이지만 awk
다음과 같은 Perl과 같은 재귀 정규식을 사용하는 솔루션보다 훨씬 느립니다.
grep -Pvx '((?:[^{}]++|\{(?1)\})*+)'
답변4
사용 awk
:
- 각 레코드에 대해 합계는 0으로 초기화됩니다.
- 한 줄씩 한 줄씩 검사를 시작하세요.
- 여는 중괄호를 처음 볼 때 합계를 늘리고, 닫는 중괄호를 볼 때 합계를 줄입니다.
- 합계가 0 아래로 떨어지면 중지하세요.
- for 루프의 끝에 도달하면 음수 합계로 인해 중간에 있거나 일반적으로 합계가 0이 아닌 경우 0이 아닌 상태로 종료됩니다.
- 참고: 이 방법은 중괄호 수를 계산하는 것과 다릅니다. 여기서는 합계가 음수가 되면 처리를 중지합니다.
awk 'BEGIN { a["{"]=1;a["}"]=-1 }
{ for (s=i=0; i++<length();) if (0>(s += a[substr($0,i,1)])) break }
s {exit 1}' file
같은 것perl
perl -lne '
local(%h,$^R) = qw/{ 1 } -1/;
/(?:(?:([{}])(?{$^R+=$h{$1}})|[^{}]+)(?(?{$^R<0})(?!)))+/g;
exit 1 if $^R;
' file
Perl은 자체 미니 프로그래밍 언어와 거의 유사한 강력한 정규식 기능을 갖추고 있습니다. 정규식 내에서 루프를 실행하고 합계를 업데이트하며 합계가 0 아래로 떨어지는 시점을 모니터링합니다.