我有一个文件,需要在某种模式后添加一组行。问题是我无法处理有多行的模式。
图案
<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,并打印所需的块。对于任何其他输入,state
将归零。
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)
.有点像 a可以通过、等s/regexp/replace/
引用捕获的片段。假设必须提取一段文本,而不是静态单词 ,并在现在出现的所有位置复制该文本:\1
\2
&
TestPlan
TestPlan
@(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
,它工作得很好,并且代码可读:多行文本按原样表示。如果该
@
字符出现,则必须将其加倍为@@
,但它没有出现。