首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >为什么Perl在previous之后没有最后一个部分时替换文本:*<hashTree/>。*</hashTree>。?

为什么Perl在previous之后没有最后一个部分时替换文本:*<hashTree/>。*</hashTree>。?
EN

Stack Overflow用户
提问于 2019-11-19 00:05:17
回答 2查看 73关注 0票数 0

我想通过Perl删除xml文件的部分( JMeter测试计划的元素),它们是:

代码语言:javascript
复制
              <hashTree>
                <JSONPathAssertion guiclass="JSONPathAssertionGui" testclass="JSONPathAssertion" testname="SON-ASS" enabled="true">
                  <stringProp name="JSON_PATH">$.status</stringProp>
                  <stringProp name="EXPECTED_VALUE">ok</stringProp>
                  <boolProp name="JSONVALIDATION">true</boolProp>
                  <boolProp name="EXPECT_NULL">false</boolProp>
                  <boolProp name="INVERT">false</boolProp>
                  <boolProp name="ISREGEX">false</boolProp>
                </JSONPathAssertion>
                <hashTree/>
              </hashTree>

tst.jmx中第一次出现JSONPathAssertion的时间是:

grep -A 10 JSONPath test7.jmx | head -n 10

代码语言:javascript
复制
</HTTPSamplerProxy>
          <hashTree>
            <JSONPathAssertion guiclass="JSONPathAssertionGui" testclass="JSONPathAssertion" testname="SON-ASS" enabled="true">
              <stringProp name="JSON_PATH">$.status</stringProp>
              <stringProp name="EXPECTED_VALUE">ok</stringProp>
              <boolProp name="JSONVALIDATION">true</boolProp>
              <boolProp name="EXPECT_NULL">false</boolProp>
              <boolProp name="INVERT">false</boolProp>
              <boolProp name="ISREGEX">false</boolProp>
            </JSONPathAssertion>
            <hashTree/>
            <JSR223PreProcessor guiclass="TestBeanGUI" testclass="JSR223PreProcessor" testname="JSR223 PreProcessor" enabled="true">

仅在第一次出现时,<hashTree/>.之后没有空格分隔的</hashTree>.

然后我写道:

代码语言:javascript
复制
cat test7.jmx | perl -0777pe 's` *<hashTree>. *<JSONPathAssertion.*?</JSONPathAssertion>. *<hashTree/>. *</hashTree>.``gs' > test7_1.jmx

然后是grep -A 10 JSONPath test7_1.jmx | head -n 10,现在输出为空。生成的文件根本没有JSONPathAssertion。为什么那个特定的事件被替换了?

附注:也许值得单独提问,但我找不到如何在perl中匹配单个换行符,只能作为更大模式的一部分:

How to match a newline \n in a perl regex?

Regex to match any character including new lines

在注释后添加:

下面的完整文件test7.jmx (再次测试,从SO复制内容并粘贴到vi到新文件),BTW全部在MacOS Mojave上完成,在CentOS 7上确认一次迭代:

代码语言:javascript
复制
<?xml version="1.0" encoding="UTF-8"?>
<jmeterTestPlan version="1.2" properties="5.0" jmeter="5.1.1 r1855137">
  <hashTree>
    <TestPlan guiclass="TestPlanGui" testclass="TestPlan" testname="test one" enabled="true">
      <stringProp name="TestPlan.comments"></stringProp>
      <boolProp name="TestPlan.functional_mode">false</boolProp>
      <boolProp name="TestPlan.tearDown_on_shutdown">true</boolProp>
      <boolProp name="TestPlan.serialize_threadgroups">false</boolProp>
      <elementProp name="TestPlan.user_defined_variables" elementType="Arguments" guiclass="ArgumentsPanel" testclass="Arguments" testname="User Defined Variables" enabled="true">
        <collectionProp name="Arguments.arguments"/>
      </elementProp>
      <stringProp name="TestPlan.user_define_classpath"></stringProp>
    </TestPlan>
    <hashTree>
      <com.blazemeter.jmeter.threads.concurrency.ConcurrencyThreadGroup guiclass="com.blazemeter.jmeter.threads.concurrency.ConcurrencyThreadGroupGui" testclass="com.blazemeter.jmeter.threads.concurrency.ConcurrencyThreadGroup" testname="Thread - main" enabled="true">
        <elementProp name="ThreadGroup.main_controller" elementType="com.blazemeter.jmeter.control.VirtualUserController"/>
        <stringProp name="ThreadGroup.on_sample_error">continue</stringProp>
        <stringProp name="TargetLevel">${__P(threads, 1)}</stringProp>
        <stringProp name="RampUp">${__P(time, 1)}</stringProp>
        <stringProp name="Steps">${__P(steps, 1)}</stringProp>
        <stringProp name="Hold">${__P(hold, 3)}</stringProp>
        <stringProp name="LogFilename"></stringProp>
        <stringProp name="Iterations"></stringProp>
        <stringProp name="Unit">M</stringProp>
      </com.blazemeter.jmeter.threads.concurrency.ConcurrencyThreadGroup>
      <hashTree>
        <GenericController guiclass="LogicControllerGui" testclass="GenericController" testname="Simple Controller - main" enabled="true"/>
        <hashTree>
          <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="REQUEST1" enabled="true">
            <boolProp name="HTTPSampler.postBodyRaw">true</boolProp>
            <elementProp name="HTTPsampler.Arguments" elementType="Arguments">
              <collectionProp name="Arguments.arguments">
                <elementProp name="" elementType="HTTPArgument">
                  <boolProp name="HTTPArgument.always_encode">false</boolProp>
                  <stringProp name="Argument.value">{&#xd;
    &quot;version&quot;: &quot;1.1&quot;,&#xd;
    &quot;test&quot;: {&#xd;
}</stringProp>
                  <stringProp name="Argument.metadata">=</stringProp>
                </elementProp>
              </collectionProp>
            </elementProp>
            <stringProp name="HTTPSampler.domain"></stringProp>
            <stringProp name="HTTPSampler.port"></stringProp>
            <stringProp name="HTTPSampler.protocol"></stringProp>
            <stringProp name="HTTPSampler.contentEncoding"></stringProp>
            <stringProp name="HTTPSampler.path"></stringProp>
            <stringProp name="HTTPSampler.method">POST</stringProp>
            <boolProp name="HTTPSampler.follow_redirects">false</boolProp>
            <boolProp name="HTTPSampler.auto_redirects">false</boolProp>
            <boolProp name="HTTPSampler.use_keepalive">true</boolProp>
            <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp>
            <stringProp name="HTTPSampler.embedded_url_re"></stringProp>
            <stringProp name="HTTPSampler.connect_timeout"></stringProp>
            <stringProp name="HTTPSampler.response_timeout"></stringProp>
          </HTTPSamplerProxy>
          <hashTree>
            <JSONPathAssertion guiclass="JSONPathAssertionGui" testclass="JSONPathAssertion" testname="JSON Assertion" enabled="true">
              <stringProp name="JSON_PATH">$.status</stringProp>
              <stringProp name="EXPECTED_VALUE">ok</stringProp>
              <boolProp name="JSONVALIDATION">true</boolProp>
              <boolProp name="EXPECT_NULL">false</boolProp>
              <boolProp name="INVERT">false</boolProp>
              <boolProp name="ISREGEX">false</boolProp>
            </JSONPathAssertion>
            <hashTree/>
            <JSR223PreProcessor guiclass="TestBeanGUI" testclass="JSR223PreProcessor" testname="JSR223 PreProcessor" enabled="true">
              <stringProp name="cacheKey">true</stringProp>
              <stringProp name="filename"></stringProp>
              <stringProp name="parameters"></stringProp>
              <stringProp name="script">// period in the past - year-month-day, set from properties in User Defined Variables

import java.time.Instant;
import java.time.temporal.ChronoUnit;
import groovy.json.JsonOutput;
import org.apache.commons.lang.RandomStringUtils;</stringProp>
              <stringProp name="scriptLanguage">groovy</stringProp>
            </JSR223PreProcessor>
            <hashTree/>
            <JSR223PostProcessor guiclass="TestBeanGUI" testclass="JSR223PostProcessor" testname="JSR223 PostProcessor" enabled="true">
              <stringProp name="cacheKey">true</stringProp>
              <stringProp name="filename"></stringProp>
              <stringProp name="parameters"></stringProp>
              <stringProp name="script">import java.time.Instant;
import java.time.temporal.ChronoUnit;</stringProp>
              <stringProp name="scriptLanguage">groovy</stringProp>
            </JSR223PostProcessor>
            <hashTree/>
          </hashTree>
          <IfController guiclass="IfControllerPanel" testclass="IfController" testname="If Controller" enabled="true">
            <stringProp name="IfController.condition">${__groovy(${random_variable} == 1)}</stringProp>
            <boolProp name="IfController.evaluateAll">false</boolProp>
            <boolProp name="IfController.useExpression">true</boolProp>
          </IfController>
          <hashTree>
            <RandomController guiclass="RandomControlGui" testclass="RandomController" testname="Random Controller" enabled="true">
              <intProp name="InterleaveControl.style">1</intProp>
            </RandomController>
            <hashTree>
              <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="REQUEST2" enabled="true">
                <boolProp name="HTTPSampler.postBodyRaw">true</boolProp>
                <elementProp name="HTTPsampler.Arguments" elementType="Arguments">
                  <collectionProp name="Arguments.arguments">
                    <elementProp name="" elementType="HTTPArgument">
                      <boolProp name="HTTPArgument.always_encode">false</boolProp>
                      <stringProp name="Argument.value">{&#xd;
    &quot;version&quot;: &quot;1.1&quot;,&#xd;
    &quot;test&quot;: {&#xd;
}</stringProp>
                      <stringProp name="Argument.metadata">=</stringProp>
                    </elementProp>
                  </collectionProp>
                </elementProp>
                <stringProp name="HTTPSampler.domain"></stringProp>
                <stringProp name="HTTPSampler.port"></stringProp>
                <stringProp name="HTTPSampler.protocol"></stringProp>
                <stringProp name="HTTPSampler.contentEncoding"></stringProp>
                <stringProp name="HTTPSampler.path"></stringProp>
                <stringProp name="HTTPSampler.method">POST</stringProp>
                <boolProp name="HTTPSampler.follow_redirects">false</boolProp>
                <boolProp name="HTTPSampler.auto_redirects">false</boolProp>
                <boolProp name="HTTPSampler.use_keepalive">true</boolProp>
                <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp>
                <stringProp name="HTTPSampler.embedded_url_re"></stringProp>
                <stringProp name="HTTPSampler.connect_timeout"></stringProp>
                <stringProp name="HTTPSampler.response_timeout"></stringProp>
              </HTTPSamplerProxy>
              <hashTree>
                <JSONPathAssertion guiclass="JSONPathAssertionGui" testclass="JSONPathAssertion" testname="JSON Assertion" enabled="true">
                  <stringProp name="JSON_PATH">$.status</stringProp>
                  <stringProp name="EXPECTED_VALUE">ok</stringProp>
                  <boolProp name="JSONVALIDATION">true</boolProp>
                  <boolProp name="EXPECT_NULL">false</boolProp>
                  <boolProp name="INVERT">false</boolProp>
                  <boolProp name="ISREGEX">false</boolProp>
                </JSONPathAssertion>
                <hashTree/>
              </hashTree>
            </hashTree>
          </hashTree>
        </hashTree>
      </hashTree>
    </hashTree>
  </hashTree>
</jmeterTestPlan>
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2019-11-19 03:45:16

This显示正在匹配的内容。文本的整个突出显示部分只是一个匹配项。.*?的匹配程度超出了您的预期。

我会使用合适的XML解析器。

代码语言:javascript
复制
use XML::LibXML qw( );

my $xpath = "
   //hashTree[
      count(*)=2 and
      *[position()=1 and name()='JSONPathAssertion'] and
      *[position()=2 and name()='hashTree' and count(*)=0]
   ]
";

my $doc = XML::LibXML->new->parse_file("a.xml");
$_->unlink for $doc->findnodes($xpath);
$doc->toFile("b.xml");

代码语言:javascript
复制
use XML::LibXML qw( );

my $doc = XML::LibXML->new->parse_file("a.xml");
for my $node ($doc->findnodes("//hashTree")) {
   my @child_eles = $node->findnodes("*");
   $node->unlink
      if @child_eles == 2
      && $child_eles[0]->nodeName eq "JSONPathAssertion"
      && $child_eles[1]->nodeName eq "hashTree"
      && $child_eles[1]->findnodes("*")->size == 0;
}

$doc->toFile("b.xml");
票数 4
EN

Stack Overflow用户

发布于 2019-11-19 15:17:46

ikegami发现了所讨论的Perl一行程序不正确工作的原因。为了便于将来参考,我在Perl中发布了正确的代码:

代码语言:javascript
复制
cat test.jmx | perl -0777pe 's` *<hashTree>\n( *)<JSONPathAssertion.*\n.*\n.*\n.*\n.*\n.*\n.*\n *</JSONPathAssertion>\n *(<hashTree/>)\n *</hashTree>\n`$1$2`g' > test_.jmx

我今天才注意到(据我所说) JMeter测试计划xml tree的所有元素都应该以子元素的<hashTree>结尾。如果不存在元素,则应写入空分支:<hashTree/>:因此,当删除分支中的单个元素时,其代码应替换为空分支的代码:<hashTree/>

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/58918621

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档