파일의 여러 줄 패턴 뒤에 여러 줄을 추가하는 방법은 무엇입니까?

파일의 여러 줄 패턴 뒤에 여러 줄을 추가하는 방법은 무엇입니까?

특정 패턴 뒤에 줄 집합을 추가해야 하는 파일이 있습니다. 문제는 여러 줄의 패턴을 처리할 수 없다는 것입니다.

무늬

<stringProp name="TestPlan.user_define_classpath"></stringProp>
</TestPlan>
<hashTree>

이 패턴 뒤에 추가할 줄

<org.apache.jmeter.config.RestServerNodeElement guiclass="TestBeanGUI"
  testclass="org.apache.jmeter.config.RestServerNodeElement"
  testname="ATC_Test_Lab" enabled="true">
<stringProp name="TestPlan.comments"> </stringProp>
<stringProp name="authbasic">${Basic}</stringProp>
<stringProp name="authpassword">ENC(dsxxxxxxxxxxxWiu+FCzl5+A==)</stringProp>
<stringProp name="authuser">${User}</stringProp>
<stringProp name="extratag"></stringProp>

sed다음 옵션으로 명령을 시도했지만 -r작동하지 않습니다

sed -i.bak '/^<stringProp
name="TestPlan.user_define_classpath"></stringProp>/{N;/\n</TestPlan>/{N;/\n<hashTree>/r
Config.jmx' $file

파일에는 Config.jmx이 패턴 뒤에 추가해야 하는 행 세트가 있습니다.

실수:-

sed: -e expression #1, char 116: unterminated `s' command

답변1

일부 스크립팅 언어에서 전체 줄을 문자열로 읽고 포함된 줄 바꿈으로 정규식 대체를 수행하는 것과 같은 지루한 접근 방식은 피합시다.

Awk의 상태 머신 메소드 각 줄을 인쇄합니다. 필요한 세 줄이 연속으로 나타나면 state변수는 2로 증가하고 필요한 블록이 인쇄됩니다. 다른 입력의 경우 state0으로 재설정됩니다.

1
1 { print state }
state == 0 && /^<stringProp name="TestPlan.user_define_classpath"><\/stringProp>$/ {
  state++; next
}
state == 1 && /^<\/TestPlan>$/ {
  state++; next
}
state == 2 && /^<hashTree>$/ {
  print \
  "<org.apache.jmeter.config.RestServerNodeElement guiclass=\"TestBeanGUI\"\n" \
  "testclass=\"org.apache.jmeter.config.RestServerNodeElement\"\n" \
  "testname=\"ATC_Test_Lab\" enabled=\"true\">\n" \
  "<stringProp name=\"TestPlan.comments\"> </stringProp>\n" \
  "<stringProp name=\"authbasic\">${Basic}</stringProp>\n" \
  "<stringProp name=\"authpassword\">ENC(dsxxxxxxxxxxxWiu+FCzl5+A==)</stringProp>\n" \
  "<stringProp name=\"authuser\">${User}</stringProp>\n" \
  "<stringProp name=\"extratag\"></stringProp>\n"
}
1 {
  state = 0;
}

여러 줄 일치 및 출력TxR. 여기서 덜 일반적인 접근 방식은 data지시어를 사용하여 입력 스트림(문자열의 게으른 목록)에서 두 지점을 캡처한 다음 Lisp 함수를 사용하여 ldiff해당 두 지점(즉, 일치하는 블록) 사이의 라인 범위를 가져오는 것입니다. 다음과 같은 방법으로 출력될 수 있습니다 tprint.

@(repeat)
@  (cases)
@    (data start)
<stringProp name="TestPlan.user_define_classpath"></stringProp>
</TestPlan>
<hashTree>
@    (data end)
@    (do (tprint (ldiff start end)))
@    (output)
<org.apache.jmeter.config.RestServerNodeElement guiclass="TestBeanGUI"
  testclass="org.apache.jmeter.config.RestServerNodeElement"
  testname="ATC_Test_Lab" enabled="true">
<stringProp name="TestPlan.comments"> </stringProp>
<stringProp name="authbasic">${Basic}</stringProp>
<stringProp name="authpassword">ENC(dsxxxxxxxxxxxWiu+FCzl5+A==)</stringProp>
<stringProp name="authuser">${User}</stringProp>
<stringProp name="extratag"></stringProp>
@    (end)
@  (or)
@line
@    (do (put-line line))
@  (end)
@(end)

이 접근 방식에서는 일치하는 코드 블록에 몇 가지 변수를 추가한 다음 와 같은 참조로 캡처할 수 있는 조각 @(output)과 같습니다. s/regexp/replace/정적 단어가 아닌 텍스트 조각을 추출하고 현재 표시되는 모든 위치에 해당 텍스트를 복사해야 한다고 가정해 보겠습니다.\1\2&TestPlanTestPlan

@(repeat)
@  (cases)
@    (data start)
<stringProp name="@TYPE.user_define_classpath"></stringProp>
</@TYPE>
<hashTree>
@    (data end)
@    (do (tprint (ldiff start end)))
@    (output)
<org.apache.jmeter.config.RestServerNodeElement guiclass="TestBeanGUI"
  testclass="org.apache.jmeter.config.RestServerNodeElement"
  testname="ATC_Test_Lab" enabled="true">
<stringProp name="@TYPE.comments"> </stringProp>
<stringProp name="authbasic">${Basic}</stringProp>
<stringProp name="authpassword">ENC(dsxxxxxxxxxxxWiu+FCzl5+A==)</stringProp>
<stringProp name="authuser">${User}</stringProp>
<stringProp name="extratag"></stringProp>
@    (end)
@  (or)
@line
@    (do (put-line line))
@  (end)
@(end)

이 버전을 사용해 봅시다:

$ txr add.txr -
foo
foo
bar 
bar
blah
blah
<stringProp name="TestPlan.user_define_classpath"></stringProp>
</TestPlan>
<hashTree>
<stringProp name="TestPlan.user_define_classpath"></stringProp>
</TestPlan>
<hashTree>
<org.apache.jmeter.config.RestServerNodeElement guiclass="TestBeanGUI"
  testclass="org.apache.jmeter.config.RestServerNodeElement"
  testname="ATC_Test_Lab" enabled="true">
<stringProp name="TestPlan.comments"> </stringProp>
<stringProp name="authbasic">${Basic}</stringProp>
<stringProp name="authpassword">ENC(dsxxxxxxxxxxxWiu+FCzl5+A==)</stringProp>
<stringProp name="authuser">${User}</stringProp>
<stringProp name="extratag"></stringProp>


blah
blah
blah
blah
<stringProp name="EvilPlan.user_define_classpath"></stringProp>  
</EvilPlan>
<hashTree>
<stringProp name="EvilPlan.user_define_classpath"></stringProp>
</EvilPlan>
<hashTree>
<org.apache.jmeter.config.RestServerNodeElement guiclass="TestBeanGUI"
  testclass="org.apache.jmeter.config.RestServerNodeElement"
  testname="ATC_Test_Lab" enabled="true">
<stringProp name="EvilPlan.comments"> </stringProp>
<stringProp name="authbasic">${Basic}</stringProp>
<stringProp name="authpassword">ENC(dsxxxxxxxxxxxWiu+FCzl5+A==)</stringProp>
<stringProp name="authuser">${User}</stringProp>
<stringProp name="extratag"></stringProp>
x
x
y
y
z
z

TestPlan로 변경 하면 EvilPlan제대로 작동하고 코드를 읽을 수 있습니다. 여러 줄의 텍스트가 있는 그대로 표시됩니다. 그 @캐릭터가 나온다면 2배로 늘려야 하는데 @@그렇지 않더군요.

관련 정보