sed, awk, grep 등을 사용하여 패턴을 기반으로 소스 코드의 메서드 주위에 "래퍼"를 추가하는 방법

sed, awk, grep 등을 사용하여 패턴을 기반으로 소스 코드의 메서드 주위에 "래퍼"를 추가하는 방법

패턴을 기반으로 파일에 래퍼를 추가하는 방법은 무엇입니까?

예를 들어 다음이 있습니다.

  ...
  find(css_policy_form_stage3).click
  with_ajax_wait
    expect(css_coverage_type_everquote).to be_visible
  end
  with_ajax_wait
    expect(css_coverage_type_everquote).to be_visible
  end
end
it "Stage 3" do
  select(coverage_type, from: css_coverage_type_everquote)
  find(css_has_auto_insurance).click
  ...

"with_ajax_wait"나는 그들 주변의 블록을 "포장" 하고 싶습니다 it "waits" do ... end.

즉, 나는 다음을 얻고 싶다:

  ...
  find(css_policy_form_stage3).click
  it "waits" do
    with_ajax_wait
      expect(css_coverage_type_everquote).to be_visible
    end
  end
  it "waits" do
    with_ajax_wait
      expect(css_coverage_type_everquote).to be_visible
    end
  do
end
it "Stage 3" do
  select(coverage_type, from: css_coverage_type_everquote)
  find(css_has_auto_insurance).click
  ...

참고 사항 및 가정:

  • 들여쓰기된 코드 블록의 길이는 항상 3줄입니다(with...expect...and end). 내가 갖고 있는 것보다 더 많은 내부 코드 줄을 허용하면 좋겠지만 가장 간단한 경우에는 필요하지 않습니다.
  • 블록 자체에는 추가로 2칸 들여쓰기가 있어야 합니다.
  • 관련되지 않은 다른 끝이 있습니다("3단계" 앞에 표시된 예).
  • expect예를 들어, 들여쓰기가 시작되는 코드 줄만 차단하도록 내부 패턴을 지정할 수 있다면 좋을 것입니다 . awk는 연속된 줄을 읽을 수 있기 때문에 도구가 될 수 있다고 생각하는데, 어떻게 작성해야 할지 막막합니다.

파일에 래퍼를 추가하는 것은 드문 일이 아니기 때문에 이것은 일반적으로 유용한 Q&A라고 생각합니다.

이전 질문과 다소 유사합니다. awk를 사용하여 간단한 규칙에 따라 소스 파일을 들여쓰는 방법은 무엇입니까?
하지만 이 경우에는 래퍼와 들여쓰기를 추가했습니다.

답변1

한 가지 방법은 다음과 같습니다 sed.

sed -E '/with_ajax_wait/,/end/{       # if line is in this range
H                                     # append to hold space
/end/!d                               # if it doesn't match end, delete it
//{                                   # if it matches
s/.*//                                # empty the pattern space
x                                     # exchange pattern space w. hold space
s/^(\n)( *)/\2it "waits" do\1\2/      # add first line + initial spacing
s/\n/&  /g                            # re-indent all other lines
G                                     # append hold space to pattern space
s/^(( *).*)/\1\2do/                   # add the closing 'do' + initial spacing
}
}
' infile

따라서 입력은 다음과 같습니다.

with_ajax_wait
  expect(css_coverage_type_everquote).to be_visible
end
  find(css_policy_form_stage3).click
  with_ajax_wait
    expect(css_coverage_type_everquote).to be_visible
  end
  something here
    with_ajax_wait
      expect(css_coverage_type_everquote).to be_visible
        got some more stuff here to do
          process it
        done
    end
  end

출력은 다음과 같습니다

it "waits" do
  with_ajax_wait
    expect(css_coverage_type_everquote).to be_visible
  end
do
  find(css_policy_form_stage3).click
  it "waits" do
    with_ajax_wait
      expect(css_coverage_type_everquote).to be_visible
    end
  do
  something here
    it "waits" do
      with_ajax_wait
        expect(css_coverage_type_everquote).to be_visible
          got some more stuff here to do
            process it
          done
      end
    do
  end

블록 이 with_ajax_wait항상 end. 필요한 경우 예제가 혼란스럽기 때문에
끝 부분을 바꾸십시오 ... ( 첫 번째 블록과 두 번째 블록에 사용함) 예를 들어 이번에는 (공백) 대신 and를 사용합니다.doendenddoBRE[[:blank:]]

sed '/with_ajax_wait/,/end/{
/with_ajax_wait/{
G
s/\([[:blank:]]*\)\(with_ajax_wait\)\(\n\)/\1it "waits" do\3  \1\2/
p
d
}
//!{
/end/!{
s/^/  /
}
/end/{
G
s/\([[:blank:]]*\)\(end\)\(\n\)/  \1\2\3\1end/
}
}
}
' infile

이렇게 하면 범위의 각 줄이 개별적으로 처리되고, 범위의 첫 번째 줄과 마지막 줄은 다시 들여쓰기되고 래퍼가 추가되며, 나머지 줄은 다시 들여쓰기됩니다.

답변2

이것은 나에게 효과적입니다 awk.

awk '/with_ajax_wait/,/end/{          # match the lines between the blocks
  i=substr($0,0,match($0, "[^ ]")-1); # i contains the indented spaces
  if($0~/with_ajax_wait/){            # if it is the starting block
    $0=i"it \"waits\" do\n  "$0       # ... add the starting block before the line
  }else if($0~/end/){                 # if it is the ending block
    $0="  "$0"\n"i"end"               # ... add the end block after the line
  }else{                              # else
    $0="  "$0                         # just indent the line with 2 spaces
  }
}1' file

댓글에 설명해주세요. 전체 문의 마지막에는 1true 조건이 있으므로 awk모든 줄이 인쇄됩니다.

답변3

다음 SED를 시도해 보세요.

sed '/with_ajax_wait/{/end/!N;N;s/^/  it \"waits\" do\n/;s/$/\nend/;s/\n/\n  /g}'

이것은 당신이 제시한 예에서 작동합니다.

맥 OS 버전

(OS X 10.8.5에서 테스트됨) Mac OS는 특정 줄 바꿈이나 세미콜론과 함께 명령을 연결하는 것을 좋아하지 않습니다. 대신 다음을 사용하십시오.

sed -E -e '/with_ajax_wait/{' -e '/end/!N' -e 'N' -e 's/^/  it \"waits\" do\
/' -e 's/$/\
end/' -e 's/\n/\
  /g' -e '}'

이는 터미널에 입력하거나 복사할 수 있는 문자 그대로의 줄바꿈입니다.

어떻게 작동하나요?

핵심은 N명령이다. 우리는 SED의 기억을 채우고 싶습니다(패턴 공간) 일련의 양식 포함

  with_ajax_wait
    // commands
  end

프로그램은 일치하는 줄에 도달할 때까지 한 번에 한 줄씩 파일을 반복한 다음 일치하는 줄에 도달할 때까지 패턴 공간에 더 많은 줄을 추가하는 명령을 with_ajax_wait실행합니다 . 프로그램의 나머지 부분은 줄 바꿈을 수행하는 일련의 대체입니다. 블록의 시작 부분에 줄을 추가하고 끝 부분에 줄을 추가한 다음 모든 것을 들여쓰기합니다. Nendit "waits" dodo

한정

  • end단어가 어디에나 나타나면 작동하지 않습니다.~에조각 with_ajax_wait ... end. 이를 달성하려면 코드 자체를 더욱 주의 깊게 분석해야 합니다. 끝이 항상 두 개의 공백으로 들여쓰기된다는 것을 보장할 수 있다면 or 로 end대체하여 이 SED를 좀 더 좋게 만들 수 있습니다 . {/end/!N{/\n end/!N
  • it "waits" doand 명령은 do내부 텍스트가 어느 정도 들여쓰기되더라도 항상 공백 두 개만큼 들여쓰기됩니다. 이 문제는 수정하기가 더 쉬울 수 있지만 명령이 더 복잡해집니다.

관련 정보