Vamos evitar abordagens chatas, como ler a linha inteira como uma string em alguma linguagem de script e fazer uma substituição de regex com novas linhas incorporadas.
Aproximação de máquina de estado no Awk. Cada linha é impressa. Se as três linhas necessárias aparecerem consecutivamente, a variável state
será incrementada para 2 e o bloco necessário será impresso. Para qualquer outra entrada, state
passa para zero.
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;
}
Correspondência de várias linhas e saída em TXR . A abordagem rara aqui é usar a diretiva data
para capturar dois pontos no fluxo de entrada (que é uma lista lenta de cadeias) e, em seguida, a função Lisp ldiff
para obter o intervalo de linhas entre esses dois pontos (ou seja, bloco que foi correspondido) para que possa ser emitido com 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)
Nesta abordagem, podemos adicionar algumas variáveis ao bloco de código correspondente e, em seguida, referir-se a elas no @(output)
. Como um s/regexp/replace/
pode se referir a peças capturadas via ,
,
&
e assim por diante. Suponha que, em vez da palavra estática TestPlan
, uma parte do texto tenha que ser extraída e a duplicada em todos os lugares em que TestPlan
aparece agora:
@(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)
Vamos tentar esta versão:
$ 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
Quando TestPlan
é alterado para EvilPlan
, funciona bem e o código é legível: o texto de várias linhas é representado como é. Se o
@
character ocorre, ele deve ser duplicado como @@
, mas isso não ocorreu.