首页 > 解决方案 > Sed(OS X)用其他文本块替换包含给定字符串的文本块

问题描述

我想用其他文件替换所有包含 Test.bundle 的行(这些行被分组在一个块中)

<ItemGroup>
  <BundleResource Include="Resources\some_other_file.json" />
  <BundleResource Include="Resources\Test.bundle\one.png" />
  <BundleResource Include="Resources\Test.bundle\two.png" />
  <BundleResource Include="Resources\Test.bundle\three.png" />
</ItemGroup>

<ItemGroup>
  <BundleResource Include="Resources\some_other_file.json" />
  <BundleResource Include="Resources\Test.bundle\four.png" />
  <BundleResource Include="Resources\Test.bundle\five.png" />
  <BundleResource Include="Resources\Test.bundle\six.png" />
  <BundleResource Include="Resources\Test.bundle\seven.png" />
</ItemGroup>

我做了什么

res=$(find Resources/Test.bundle -type f | sed 's/\\/\//g' | xargs -I {} echo "<BundleResource Include=\"{}\" />") #get new files, change path delimiters, wrap file names in output pattern
sed -E -i '' '/Test\.bundle/,/ItemGroup/c\
BUNDLE_PLACEHOLDER' file.ext #remove whole block from first line containing Test.bundle to closing ItemGroup and replace with placeholder
sed -E -i '' "s:BUNDLE_PLACEHOLDER:$res:" file.ext #replace with new block

由于我无法在第三个命令中一次性更改它,"extra characters after \ at the end of c command"因此我将其更改为我试图在下一个命令中替换的字符串占位符。这也失败了unescaped newline inside substitute pattern,因为我目前正在尝试解决。还缺少将在稍后添加的关闭 ItemGroup 标记。

还有其他使用 sed 的选项吗?

我可以只捕获包含 Test.bundle 的组而不捕获关闭 ItemGroup 吗?

如何转义换行符以满足替换模式?

标签: regexbashmacossed

解决方案


目前尚不清楚您真正想要匹配的是什么,但这可能是您想要的:

awk '
NR==FNR {
    new = new $0 ORS
    next
}
/Test\.bundle/ {
    printf "%s", new
    new = ""
    next
}
{ print }
' new old

例如:

$ cat old
<ItemGroup>
  <BundleResource Include="Resources\some_other_file.json" />
  <BundleResource Include="Resources\Test.bundle\one.png" />
  <BundleResource Include="Resources\Test.bundle\two.png" />
  <BundleResource Include="Resources\Test.bundle\three.png" />
</ItemGroup>

$ cat new
  <BundleResource Include="Resources\Test.bundle\four.png" />
  <BundleResource Include="Resources\Test.bundle\five.png" />
  <BundleResource Include="Resources\Test.bundle\six.png" />
  <BundleResource Include="Resources\Test.bundle\seven.png" />

.

$ awk '
NR==FNR {
    new = new $0 ORS
    next
}
/Test\.bundle/ {
    printf "%s", new
    new = ""
    next
}
{ print }
' new old
<ItemGroup>
  <BundleResource Include="Resources\some_other_file.json" />
  <BundleResource Include="Resources\Test.bundle\four.png" />
  <BundleResource Include="Resources\Test.bundle\five.png" />
  <BundleResource Include="Resources\Test.bundle\six.png" />
  <BundleResource Include="Resources\Test.bundle\seven.png" />
</ItemGroup>

推荐阅读