괄호 안의 줄에서만 어떻게 작업을 수행할 수 있나요?
예를 들어, ".is" 줄을 변경하고 대괄호를 추가하고 싶지만 닫히지 않은 대괄호가 있는 줄은 변경하지 않으려고 합니다.
그래서 이것들이 바뀌었어요
this_thing.is 24 -> (this_thing).is 24
that.is 50 -> (that).is 50
a[23].is == 10 -> a[23].is == 10
a.is true -> (this_thing).is 24
this_thing.is 24 -> (this_thing).is 24
그러나 이것들은 그렇지 않습니다:
this_thing.is (24
((that).is 50
(a[23].is == 10
a.is ( true
(this_thing.is 24
이상적으로는 둘 다 아니다(아님)
a{.is true
this_thing{.is 24
설마)
a[.is true
this_thing[.is 24
/.is/가 있는 일치자가 있는데 일치하지 않는 대괄호를 어떻게 일치시키나요?
답변1
개인적으로 내 정규 표현식이 이 수준의 복잡성에 가까웠다면 전체 작업을 Perl로 전환하겠습니다. 이것은 여러 개의 여는 중괄호/둥근 대괄호/중괄호를 처리합니다.
$ perl -ne '@open=/[\[({]/g; @close=/[)\]}]/g;
if($#close == $#open){s/(.+?)\.is/($1).is/} print' file
또는 더 간단하게는 다음과 같습니다.
$ perl -pne 's/(.+?)\.is/($1).is/ if $#{/[\[({]/g} == $#{/[)\]}]/g}' file
또는 더 완벽하게, 유사한 상황을 처리하는 다음과 같습니다 [}
(그러나 유사한 상황에서는 여전히 실패합니다 )(
).
$ perl -pne '@osqb=/\[/g; @csqb=/\]/g;
@ocb=/\{/g; @ccb=/\}/g;
@op=/\(/g; @cp=/\)/g;
if($#osqb == $#csqb && $#ocb==$#ccb && $#op == $#cp){
s/(.+?)\.is/($1).is/
}' file
귀하의 예제를 실행하면 인쇄됩니다
(this_thing).is 24
(that).is 50
(a[23]).is == 10
(a).is true
(this_thing).is 24
this_thing.is (24
((that).is 50
(a[23].is == 10
a.is ( true
(this_thing.is 24
a{.is true
this_thing{.is 24
a[.is true
this_thing[.is 24
설명하다
perl -ne
: 입력 파일을 한 줄씩 처리-n
하고( ) 주어진 스크립트를 실행합니다-e
.@open=/[\[({]/g;
: 열려 있는 모든 문자 모양을 찾아 결과를 이름이 지정된 배열에 저장합니다@open
.@close=/[)\]}]/g;
: 위와 같지만 글리프를 끄는 데 사용됩니다.if($#close == $#open)
: 왼쪽 글리프 개수가 오른쪽 글리프 개수와 같은 경우(즉, 괄호 등이 있는 경우)...s/(.+?)\.is/($1).is/
.is
: ...then은 괄호 안의 자신으로 끝나는 가장 짧은 문자열을 바꿉니다.- 마지막 것은
print
대괄호 밖에 있으며 대체 여부에 관계없이 실행됩니다.
답변2
terdon의 답변을 확장하면 Perl을 사용하여 실제로 중첩된 대괄호 구조를 구문 분석할 수 있습니다. 다음은 이 작업을 수행하는 정규식입니다.
$balanced_parens_grammar = qr/
(?(DEFINE) # Define a grammar
(?<BALANCED_PARENS>
\( # Opening paren
(?: # Group without capturing
(?&BALANCED_PARENS) # Nested balanced parens
|(?&BALANCED_BRACKETS) # Nested balanced brackets
|(?&BALANCED_CURLIES) # Nested balanced curlies
|[^)]* # Any non-closing paren
) # End alternation
\) # Closing paren
)
(?<BALANCED_BRACKETS>
\[ # Opening bracket
(?: # Group without capturing
(?&BALANCED_PARENS) # Nested balanced parens
|(?&BALANCED_BRACKETS) # Nested balanced brackets
|(?&BALANCED_CURLIES) # Nested balanced curlies
|[^\]]* # Any non-closing bracket
) # End alternation
\] # Closing bracket
)
(?<BALANCED_CURLIES>
{ # Opening curly
(?: # Group without capturing
(?&BALANCED_PARENS) # Nested balanced parens
|(?&BALANCED_BRACKETS) # Nested balanced brackets
|(?&BALANCED_CURLIES) # Nested balanced curlies
|[^}]* # Any non-closing curly
) # End alternation
} # Closing curly
)
)
(?<BALANCED_ANY>
(?:
(?&BALANCED_PARENS)
|(?&BALANCED_BRACKETS)
|(?&BALANCED_CURLIES)
)
)
/x;
다음과 같이 사용하세요:
if( $line =~ m/
^
[^()\[\]{}]* # Any non-parenthetical punctuation
(?&BALANCED_ANY)? # Any balanced paren-types
[^()\[\]{}]*
$
$balanced_parens_grammar/x){
# Do your magic here
}
부인 성명
코드는 완전히 테스트되지 않았습니다. 오류가 있을 수 있습니다.
답변3
Sed는 정규식을 사용하는데, 이는 이에 대해 충분히 강력하지 않습니다. 이를 수행할 수 있는 gawk 또는 다른 도구를 사용하십시오.
이를 나타내는 문법 분류에는 일반 문법, 문맥 자유 문법 등이 있습니다. 일반 언어에서는 대괄호 일치를 수행할 수 없습니다. 따라서 이 작업을 안정적으로 수행할 수 없습니다.