sed - 일치하지 않는 괄호를 일치시키지 않는 방법

sed - 일치하지 않는 괄호를 일치시키지 않는 방법

괄호 안의 줄에서만 어떻게 작업을 수행할 수 있나요?

예를 들어, ".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 또는 다른 도구를 사용하십시오.

이를 나타내는 문법 분류에는 일반 문법, 문맥 자유 문법 등이 있습니다. 일반 언어에서는 대괄호 일치를 수행할 수 없습니다. 따라서 이 작업을 안정적으로 수행할 수 없습니다.

관련 정보