我正在尝试清理代码生成器的输出。不幸的是它会生成多个导入:
import Foo
...
import Foo
幸运的是,生成的文本相对静态,尽管它经常重新生成,因此我希望有一种简单的方法可以删除它。
我发现如果他们在同一条线上我可以:sed 's/import Foo//2g'
但是我不知道足够的 sed 来让它只考虑所有行。
一个 hacky 解决方案是运行多个 sed...
sed 's/\n/<string I know doesn't appear>/g'
sed 's/import Foo//2g'
sed 's/<string I know doesn't appear>/\n'
但这样做感觉不对。有一个更好的方法吗?
答案1
sed '/^import Foo$/{x;/^$/!d;g;}'
工作原理:在与模式匹配的每一行上
x
:将行与保留空间交换/^$/!d
:如果刚刚从保存空间获取的内容不为空,即。因为之前的匹配项存储在那里,所以删除该模式并前进到下一行g
:否则(即第一次通过)将保存的行复制回来。默认情况下会打印
答案2
使用 GNU 实现sed
(您可能正在使用它,因为您已经使用了 GNUism 2g
),您可以这样做:
sed '0,/import Foo/!{//d}' < file
import Foo
这将删除除第一行之外的所有行。/^import Foo$/
如果您只想删除符合以下条件的行,请将模式替换为正是 import Foo
。
您也可以awk
在这里使用:
awk '!/import Foo/ || !n++' < file
答案3
如果您的sed
版本允许,请尝试
sed -z 's/import Foo//2g' file
答案4
保持简单、可移植等,并且必须使用 awk:
$ cat file
import Foo
import Bar
import More
import Foo
import Stuff
import Bar
$ awk '!seen[$0]++' file
import Foo
import Bar
import More
import Stuff
或者,如果只是以您想要使其唯一的行开头import
,并且输入中还有您不想触及的其他行:
$ cat file
import Foo
int 3;
import Bar
char 7;
import More
int 3;
import Foo
char 7;
import Stuff
whatever
import Bar
whatever
$ awk '!(/^import/ && seen[$0]++)' file
import Foo
int 3;
import Bar
char 7;
import More
int 3;
char 7;
import Stuff
whatever
whatever