如何防止 sed 插入空格?

Posted

技术标签:

【中文标题】如何防止 sed 插入空格?【英文标题】:How can I prevent sed from inserting blanks? 【发布时间】:2021-11-01 17:18:45 【问题描述】:

我编写这段代码是为了从一个文件中提取软件版本并在另一个文件中覆盖它:

newVersion=$(sed -r -n 's/<version>(.*-SNAPSHOT)<\/version>/\1/p' sa-pom.xml)
find ./pom.xml -type f -exec sed -r -i -e "s/<version>(.*-SNAPSHOT)<\/version>/<version>$newVersion<\/version>/g"  \;
echo '<version>'$newVersion'</version>'

它可以工作,但它在支持变量中放置一个空格,在目标文件中放置三个空格,分别生成以下输出:

<version> 0.19.6-SNAPSHOT</version>
<version>   0.19.6-SNAPSHOT</version>

这是 sa-pom.xml 文件的剪辑版:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>my-group-id</groupId>
    <artifactId>my-artifact-id</artifactId>
      <version>0.19.9-SNAPSHOT</version>

    <packaging>jar</packaging>

    <name>my-project-name</name>

</project>

这是 pom.xml 文件的剪辑版:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <parent>
        <groupId>my-group-id</groupId>
        <artifactId>my-parent-artifact-id</artifactId>
        <version>$revision</version>
    </parent>

    <artifactId>my-artifact-id</artifactId>
      <version>0.19.8-SNAPSHOT</version>

    <packaging>jar</packaging>

    <name>my-project-name</name>

</project>

如何解决?

【问题讨论】:

在版本号中使用-SNAPSHOT 可能会成为计算机历史上最糟糕的做法。 【参考方案1】:

sed 并没有真正在此处添加任何空格,但它会捕获任何已经存在的空格,并将它们保留在替换中。但是,只需扩展您的正则表达式以避免捕获任何空格。

newVersion=$(sed -n -r 's%.*<version>[[:space:]]*(.*-SNAPSHOT)</version>.*%\1%p' sa-pom.xml)
sed -r -i "s%<version>[[:space:]]*(.*-SNAPSHOT)</version>%<version>$newVersion</version>%" pom.xml
echo "<version>$newVersion</version>"

&lt;version&gt; 之前添加.* 会删除行中的前导空格(以及&lt;version&gt; 标记之前的任何其他文本)。我还在&lt;/version&gt; 之后添加了.* 以修剪结束标记之后的任何文本,只是为了保持它的健壮性。

在捕获之前添加[[:space:]]* 可确保捕获的表达式中不会包含任何空格,因为正则表达式引擎将尽可能多地跳过,并且永远不需要从那里回溯以获得匹配(如果它回溯,这是因为它根本找不到匹配项)。 如果这听起来太复杂,让我们更广泛地说,正则表达式引擎更喜欢最长最左边的匹配,因此匹配捕获组之外的空格可以避免它们。

find 在这里似乎也完全是多余的。 您会注意到我还切换了s%..%..% 分隔符,以避免必须使用反斜杠转义斜杠。 /g 标志似乎也没有必要(除非您真的希望每行有多个匹配项,但是您不能在搜索中使用.*,因为它会吃掉第一个匹配项和最后一个匹配项之间的所有文本)。如果您的脚本仅包含单个字符串(并且不以破折号开头),则 -e 并不是真正需要的。最后,我修复了echo 中的引用。

这还是很脆弱的;理想情况下,使用可识别 XML 的工具来解析 XML 文件中的值。

【讨论】:

以上是关于如何防止 sed 插入空格?的主要内容,如果未能解决你的问题,请参考以下文章

sed / awk - 使用模式匹配后插入空格

如何防止文本区域中的重复空格

sed 在指定行插入?

sed 怎样在文本里指定位置插入字符

防止 JavaScript 自动插入分号

sed 在匹配行前后添加内容