我有一个以下格式的文件。
I PRP B-PRP
am VBP B-VBP
a DT B-DT
happy JJ B-JJ
soul NN B-NN
I PRP B-PRP
am VBP B-VBP
a DT B-DT
sad JJ B-JJ
soul NN B-NN
每条记录都用空行分隔。每行有3个字段。
如果有输入我是一个快乐的灵魂我想在此文件中搜索并删除记录(如果它存在)。在此示例中,将从文件中删除记录1。由于句子分为多行,我无法弄清楚如何做到这一点。我尝试了 sed , awk , grep 。似乎没什么用。基本上,我无法弄清楚如何为这些命令提供模式。
sed -e '/I/,/soul/!d' filename
大多数评论与上述类型相似,开始模式后跟结束模式。但这不符合我的情况。
如何解决这个问题?
答案 0 :(得分:3)
如果有输入我是一个快乐的灵魂我想在此文件中搜索并删除该记录(如果它存在)。
您可以使用此awk
命令:
awk -v RS= '!/^I .*\nam .*\nhappy .*\nsoul /' file
I PRP B-PRP
am VBP B-VBP
a DT B-DT
sad JJ B-JJ
soul NN B-NN
答案 1 :(得分:2)
使用AWK可以将RS
(记录分隔符)设置为空,以便在空行上分割记录:
$ awk '/I.*am.*happy.*soul/' RS= input.txt
I PRP B-PRP
am VBP B-VBP
a DT B-DT
happy JJ B-JJ
soul NN B-NN
.*
是两个正则表达式元字符,.
表示任何字符,而*
表示零次或多次。
我不确定.
匹配换行符的定义有多好。
答案 2 :(得分:1)
确切的方法(订单除外,需要a[$i]=i
和... ("am" in a) && a["I"]<a["am"] && ...
):
$ awk -v RS= '
{
delete a;
for(i=1;i<=NF;i++) # iterate every word
a[$i] # and store it
}
("I" in a) && ("am" in a) && ("a" in a) && ("happy" in a) && ("soul" in a) {next} 1
' test
I PRP B-PRP
am VBP B-VBP
a DT B-DT
happy JJ B-JJ
soul NN B-NN
编辑:测试精确单词匹配的版本以及块中单词的顺序(在本例中为记录)并接受搜索到的单词作为参数(请参阅{{1}在代码中):
s
(*)我没有测试如果在单词块中存在两次想要的单词会发生什么。最后一个位置仍然是那个词,所以去图......
答案 3 :(得分:1)
这可能适合你(GNU sed):
sed ':a;N;/^$/M!ba;/I.*am.*a.*happy.*soul/d' file
在遇到空行时,在模式空间中读取多行,匹配所需的字符串并在必要时删除。
更灵活的解决方案可能是:
sed ':a;$!{N;/^\s*$/M!ba};/\<I\>.*\<am\>.*\<a\>.*\<happy\>.*\<soul\>/d' file