【问题标题】:Sed (OS X) replace block of text containing given string with other block of textSed(OS X)用其他文本块替换包含给定字符串的文本块
【发布时间】:2020-12-15 08:11:50
【问题描述】:

我想用其他文件替换所有包含 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 吗?

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

【问题讨论】:

    标签: regex bash macos sed


    【解决方案1】:

    首先,sed 并不是您最好的选择,但因为您要求sed...
    这是粗略的第一遍。

    $: cat new
    <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>
    
    $: cat old
    stuff before
    
    ...
    
    more stuff
    
    <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>
    
    stuff after
    
    ...
    
    more stuff.
    
    $: sed -n '/<ItemGroup>/,/<[/]ItemGroup>/{ /<ItemGroup>/h;
         /<[/]ItemGroup>/{ H; s/^.*//; x; /Test[.]bundle/{ s/^.*/cat new/e; }; p; d; }
         H; d; }; p; ' old
    stuff before
    
    ...
    
    more stuff
    
    <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>
    
    stuff after
    
    ...
    
    more stuff.
    

    这显然对您的文件结构做了一些简单的假设。

    awk中的逻辑相同:

    awk 'NR == FNR { new=new$0"\n"; next; }
      /<ItemGroup>/,/<[/]ItemGroup>/{ grp=grp$0"\n";
        if ($0 ~ "</ItemGroup>") { if (grp ~ "Test.bundle") { print new } else { print grp } grp="" } else next;
      } 1' new old
    

    【讨论】:

    • 感谢您的宝贵时间。不幸的是,OS X sed 似乎与 e 参数不兼容,并在替代命令中抛出错误标志:'e'
    • 你试过awk吗?
    【解决方案2】:

    不清楚你真正想要匹配的是什么,但这可能是你想要的:

    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>
    

    【讨论】:

      猜你喜欢
      • 2012-10-14
      • 2016-02-07
      • 1970-01-01
      • 1970-01-01
      • 2020-12-04
      • 2021-11-20
      • 1970-01-01
      • 1970-01-01
      • 2020-01-19
      相关资源
      最近更新 更多