使用SED查找范围并复制它

时间:2017-01-27 20:08:11

标签: linux bash macos sed

在Mac OSX上,我需要编写脚本以成为Linux的跨平台,因为GNU sed和OSX sed之间存在差异。

我有一个文件,它使用范围表达式告诉我的脚本复制整个范围。这是我目前的解决方案。我已尝试使用/ a和/ i使用各种 - 标志,并且我不断收到多个地址错误。

#!/bin/bash
...

stream=$(`cat file.txt`)
for i in 3; do
  stream=$(echo "$stream" | sed '/%%RANGE_STUB/,/%%/ p ')
done

截至目前,这需要我的文件并复制其自身内部的范围。我需要它之后

这是文件:

Some text here. 

%%RANGE_STUB
This content is copied and preserved including the RANGE_STUB and double % symbols
%%

这是输出:

Some text here.

%%RANGE_STUB
%%RANGE_STUB
%%RANGE_STUB
This contents is copied and preserved including the RANGE_STUB and double % symbols
%%
%%
%%

这是所需的输出:

Some text here.

%%RANGE_STUB
This contents is copied and preserved including the RANGE_STUB and double % symbols
%%

%%RANGE_STUB
This contents is copied and preserved including the RANGE_STUB and double % symbols
%%

%%RANGE_STUB
This contents is copied and preserved including the RANGE_STUB and double % symbols
%%

3 个答案:

答案 0 :(得分:2)

您可以在OSX上使用awk代替sed

awk '/%%RANGE_STUB/{p=1} p{s = s RS $0} 1;
     p && /%%$/{for(i=1; i<=3; i++) print s; p=0; s=""}' file

Some text here.

%%RANGE_STUB
This content is copied and preserved including the RANGE_STUB and double % symbols
%%

%%RANGE_STUB
This content is copied and preserved including the RANGE_STUB and double % symbols
%%

%%RANGE_STUB
This content is copied and preserved including the RANGE_STUB and double % symbols
%%

%%RANGE_STUB
This content is copied and preserved including the RANGE_STUB and double % symbols
%%

答案 1 :(得分:2)

$ cat tst.awk
/%%RANGE_STUB/ { inBlock = 1 }
inBlock {
    block = block $0 ORS
    if (/%%$/) {
        for (i=1; i<=3; i++) {
            print block
        }
        inBlock = 0
    }
    next
}
{ print }
$
$ awk -f tst.awk file
Some text here.

%%RANGE_STUB
This content is copied and preserved including the RANGE_STUB and double % symbols
%%

%%RANGE_STUB
This content is copied and preserved including the RANGE_STUB and double % symbols
%%

%%RANGE_STUB
This content is copied and preserved including the RANGE_STUB and double % symbols
%%

答案 2 :(得分:0)

对于两个副本(一个重复传递),没有添加的换行符:

echo "$stream" | sed -e '/%%RANGE_STUB/,/%%/{//\!H;/%%RANGE_STUB/h;/%%$/{H;G}}'

或(不同的命令分组,相同的效果):

echo "$stream" | sed -e '/%%RANGE_STUB/,/%%/{//\!H};/%%RANGE_STUB/h;/%%$/{H;G}'

这些是做什么的:

  • h - 替换保留空间 - 作为范围的第一行
  • H - 附加到保留空间 - 用于范围的中间行
  • H;G - 追加持有空间,然后追加整个持有空间 - 为该范围的最后一行。

//\!//!的转义版本,这意味着与之前的模式不匹配,因此它匹配范围中的中间行。

您的结束模式已更改为/%%$/,以确保它仅匹配H;G

范围的最后一行

你得到:

Some text here.

%%RANGE_STUB
This contents is copied and preserved including the RANGE_STUB and double % symbols
%%
%%RANGE_STUB
This contents is copied and preserved including the RANGE_STUB and double % symbols
%%

使用sed非常困难,我想通过重复的脚本调用来获得3份副本。你可以通过重复sed获得2的幂 - 每次调用都会使副本加倍。

因此,对于3份副本,您可以在一个脚本中执行此操作:

echo "$stream" | sed -e '/%%RANGE_STUB/,/%%/{//\!H};/%%RANGE_STUB/h;/%%$/{H;G;G}'

Some text here.

%%RANGE_STUB
This contents is copied and preserved including the RANGE_STUB and double % symbols
%%
%%RANGE_STUB
This contents is copied and preserved including the RANGE_STUB and double % symbols
%%
%%RANGE_STUB
This contents is copied and preserved including the RANGE_STUB and double % symbols
%%

可以想象,您可以在包装器脚本中使用可变数量的;G命令构造字符串。