2014-08-28 45 views
0

我想根据其ID删除bibtex文件 中第一次出现的条目。例如,假设我们有这样的文件:如何使用sed删除bibtex条目的第一次出现?

@inproceedings{id1, 
    author = "", 
    title = "", 
    ... 
} 

@inproceedings{id2, 
    author = "", 
    title = "", 
    ... 
} 

@misc{id1, 
    author = "", 
    title = "", 
    ... 
} 

而且我想删除包含ID1中的第一项,所以我想 输出为:

@inproceedings{id2, 
    author = "", 
    title = "", 
    ... 
} 

@misc{id1, 
    author = "", 
    title = "", 
    ... 
} 

我想要的自动化的方式使用sed来做到这一点。直到现在我有这个:

sed '/^@.*{id1/, /}/d' input_file 

但是这会删除文件中的所有事件。你能帮我找到一种方法 只是删除第一个?

回答

3

这可能为你工作(GNU SED) :

sed 'x;/./{x;b};x;/^@.*{id1/,/}/{/}/h;d}' file 

一旦第一次发生被删除,在保持空间中设置一个标记如果该标志被设置,忽略文件末尾的其他行。

编写sed命令时可以使用两个寄存器。 Sed会将当前行(减去换行符)放在模式空间(PS)中,第二个寄存器调用保持空间(HS)。 x交换HS的PS,h将PS复制到HS。 sed一行脚本交换HS的PS,检查HS的任何字符/./,如果这种情况为真,则为PS重新交换HS并释放。如果条件不成立,则HS将被重新调入PS并执行进一步的命令。范围条件查找/^@.*{id1/,/}/这是包含在两个字符串之间的所有行,如果发现这些行被删除,但是如果当前行被发现是结束条件,则该行被复制到HS。 /}/h。现在后面的行将被忽略到文件的末尾。

+0

很酷!它有效,但我不明白它的作用。你能给我更多关于它是如何工作的信息吗?我也会尝试在Google中搜索详细信息。谢谢! – 2014-08-28 16:27:14

+1

@ThanasisPetsas见编辑。 – potong 2014-08-28 16:56:25

+0

非常感谢您的描述!我不知道这些注册。他们似乎非常有帮助! – 2014-08-29 11:08:13

1

用awk可以用自定义的RS(记录分隔符)做这样的:

awk -v RS= -v ORS='\n\n' '!/@inproceedings{id1/' f 
@inproceedings{id2, 
    author = "", 
    title = "", 
     ... 
} 

@misc{id1, 
    author = "", 
    title = "", 
     ... 
} 
+0

我会搜索“id1”而不是假设它是第一个。 – 2014-08-28 13:47:20

+0

是的,我可以搜索,但我虽然OP只是想删除第一个条目。让我在我的答案中补充一点。 – anubhava 2014-08-28 13:48:05

+0

对!我想删除一些内容,就像我在问题中提到的那样。 – 2014-08-28 13:48:30

1
sed '/^@inproceedings{id1,/,/}/ d' YourFile 

删除部分的每一行(/start/,/end/ action

+0

但是,如果** id1 **的条目都具有属性'inproceedings',它们都将被删除,但是我只想删除第一条.. – 2014-08-28 13:55:15

+0

确切的。调整您的示例,我会尝试修改代码。我只看到波通已经添加了一个更好的代码,包括这个评论:-) – NeronLeVelu 2014-08-29 05:45:10

1

sed是一个很好的工具,可以简单地替换一行代码,但对于所有其他文本操作,您应该使用awk。

$ awk -v type="inproceedings" -v id="id1" -v RS= -v ORS='\n\n' -F'[@{,]' '!($2 == type && $3 == id)' file 
@inproceedings{id2, 
    author = "", 
    title = "", 
    ... 
} 

@misc{id1, 
    author = "", 
    title = "", 
    ... 
} 

$ awk -v type="inproceedings" -v id="id2" -v RS= -v ORS='\n\n' -F'[@{,]' '!($2 == type && $3 == id)' file 
@inproceedings{id1, 
    author = "", 
    title = "", 
    ... 
} 

@misc{id1, 
    author = "", 
    title = "", 
    ... 
} 

$ awk -v type="misc" -v id="id1" -v RS= -v ORS='\n\n' -F'[@{,]' '!($2 == type && $3 == id)' file 
@inproceedings{id1, 
    author = "", 
    title = "", 
    ... 
} 

@inproceedings{id2, 
    author = "", 
    title = "", 
    ... 
} 

,如果你想选择匹配,而不是不匹配的那些块,刚刚摆脱!在280℃情况的开始。

所有用于处理多行代码块的sed语言结构(即,除s,g和p之外的所有内容都带有-n)在20世纪70年代中期发明时就已经过时了,所以当你忽略它们时永远不需要他们。获取Arnold Robbins编写的Effective Awk Programming(第三版有效Awk编程)一书,然后花费大量时间。

+1

非常感谢!这个解决方案也很棒。但是当我要求一个基于'sed'的解决方案时,我接受了potong的答案。尽管如此,'awk'是一个了不起的命令/语言!谢谢你的建议。 – 2014-08-29 11:11:54

+0

不客气。自从您提出要求之后,接受基于sed的解决方案是完全合理的。当然不要使用它,因为这会导致经常听到的sed咒语'酷!它可以工作,但我不明白它做了什么,而只是尝试修改它,以便以不同方式或附加方式完成最简单的事情。当block中缺少'author'时,向stderr发送消息:-)。 – 2014-08-29 12:03:37

相关问题