用正则表达式替换Powershell中字符串的一部分

时间:2016-03-17 16:52:04

标签: regex powershell

我遇到了问题:

我有一个XML文件,其中包含:

<colortable>
<color id="1" type="transparent"/>
<color id="2"/>
<color id="3" values="1.0"/>
<color id="4" type="rgb" values="0.0,0.0,0.0"/>
<color id="5" type="rgb" values="1.0,1.0,1.0"/>
</colortable>
<imagetable>
<imagedata id="1" source="E:\xml2pdf_universal_physical_layer\tmp\dbres22C79BB2A484491458226919210\r.437248.1395746975.csfolha1v2SemMensagem_Tim.jpg">
</imagedata>
<imagedata id="2" source="E:\xml2pdf_universal_physical_layer\tmp\dbres22C79BB2A484491458226919210\r.42189.1400584131.csfolha2v2fiscal_Tim.jpg">
</imagedata>
<imagedata id="3" source="E:\xml2pdf_universal_physical_layer\tmp\dbres22C79BB2A484491458226919210\r.488328.1422006304.DT1_Image6_T.jpg">
</imagedata>
<imagedata id="4" source="E:\xml2pdf_universal_physical_layer\tmp\dbres22C79BB2A484491458226919210\r.1262464.1427173896.csfolha3v2fiscal_Tim.jpg">
</imagedata>
<imagedata id="5" source="E:\xml2pdf_universal_physical_layer\tmp\dbres22C79BB2A484491458226919210\r.54571.1400584131.csfolha0v2fiscal_Tim.jpg">
</imagedata>
</imagetable>

我想要将上面的路径更改为C:\images\

我试图使用这个Powershell代码:

while ($line = [Console]::In.ReadLine()) 
{ 
  switch -wildcard ($line) 
  { 
   '<imagedata*' {$line -replace '[A-Z]{1}:.+[r][.]([0-9]+[.]){2}', 'c:\images\'} 
   default {$line}
  }
}

我希望这样,对于以<imagedata开头的每个字符串,找到路径(匹配正则表达式)并将其替换为新路径。

这不起作用。我该如何解决?

1 个答案:

答案 0 :(得分:1)

之前我没有使用过PowerShell,但是我在RegEx标签下看到了这个,所以我想我会看一下。我相信你的问题来自::.+[r]。这是一个贪婪的运算符,可能会导致一些问题。也许尝试以下方法:

while ($line = [Console]::In.ReadLine()) 
{ 
  switch -wildcard ($line) 
  { 
   '<imagedata*' {$line -replace '[A-Za-z]:.+?r\.(\d+\.){2}', 'c:\images\'} 
   default {$line}
  }
}

添加问号(?)会使+变得愚蠢,而不是贪婪,这样就可以让您正确地使用r.######.#######.(包括)的任何内容。我还用[.]替换了\.以表示一段时间标记,我将[0-9]\d交换(这只是一种较短的编写方式)。但是,如有人指出评论,您确定要替换r.######.#######.部分吗?

如果您最终希望保留文件名的r.######.########.部分,则可以通过使用RegEx正向前瞻操作符而不是实际匹配来完成此操作。但是,作为警告,当前瞻/后视的文字长度未指定/可确定时,某些RegEx引擎实现会抛出拟合。我不确定PowerShell如何处理不同长度的前瞻,但这是一个使用它的实现(假设PowerShell支持它):

while ($line = [Console]::In.ReadLine()) 
{ 
  switch -wildcard ($line) 
  { 
   '<imagedata*' {$line -replace '[A-Za-z]:.+?(?=r\.(\d+\.){2})', 'c:\images\'} 
   default {$line}
  }
}

例如,在您的行中显示:E:\xml2pdf_universal_physical_layer\tmp\dbres22C79BB2A484491458226919210\r.437248.1395746975.csfolha1v2SemMensagem_Tim.jpg,而不是替换:E:\xml2pdf_universal_physical_layer\tmp\dbres22C79BB2A484491458226919210\r.437248.1395746975.,理论上,第二个代码只会替换:E:\xml2pdf_universal_physical_layer\tmp\dbres22C79BB2A484491458226919210\。因此,它将保留整个文件名。同样,这取决于PowerShell对前瞻的支持,你可能实际上想要替换文件名的第一部分,但我只是想在这里作为替代,以防你确实想要保留整个文件名。 / p>

我希望有所帮助。如果有什么不清楚,请告诉我。您可以通过clicking here (link to regular-expressions.info)了解有关RegEx的更多信息,特别是前瞻和后瞻。