Como adicionar múltiplas linhas em um arquivo depois de um padrão que também é multi-linha?

1

Eu tenho um arquivo onde eu preciso adicionar um conjunto de linhas depois de algum padrão. O problema é que eu não sou capaz de lidar com o padrão que tem várias linhas.

Padrão

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

Linhas a serem adicionadas após esse padrão

<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>

Eu tentei o comando sed com a opção -r como abaixo, mas não funcionou

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

arquivo Config.jmx tem o conjunto de linhas que precisam ser adicionadas após esse padrão.

Erro: -

sed: -e expression #1, char 116: unterminated 's' command
    
por Beginner 07.09.2016 / 08:31

1 resposta

0

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.

    
por 15.09.2016 / 06:38

Tags