有一个讨厌的文本操作问题,我需要删除文件中的一行,如果它包含一个字符串,但只有当下一行还包含另一个字符串时。例如,我有这些行:
john paul
george
john paul
12
john paul
我想删除任何包含' john paul'如果紧接着是包含' george'的行,那么它将返回:
george
john paul
12
john paul
不确定如何grep或sed这个。如果有人能伸出援助之手,那就太棒了!
答案 0 :(得分:2)
这可能适合你(GNU sed):
sed '/john paul/{$!N;/\n.*george/!P;D}' file
如果该行包含john paul
,请阅读下一行,如果该行包含george
,请不要打印第一行。
N.B。如果包含george
的行包含john paul
,则也会对其进行检查。
答案 1 :(得分:1)
此awk
应该:
cat file
john paul
george
john paul
12
john paul
hans
george
awk 'f~/john paul/ && /george/ {f=$0;next} NR>1 {print f} {f=$0} END {print}' file
george
john paul
12
john paul
hans
george
如果george
john paul
上方的名称
答案 2 :(得分:1)
awk 'NR > 1 && !(/george/ && p ~ /john paul/) { print p } { p = $0 } END { print }' file
输出:
george
john paul
12
john paul
答案 3 :(得分:1)
这是一个更通用的版本:
如果这些行匹配一个字符串而前一行恰好是“john paul”则不执行任何操作,否则,打印上一行。 (如果您只想检测^[a-zA-Z]$
,请将george
部分更改为george
。
awk '!(/^[a-zA-W]+$/ && previous ~/^john paul$/){print previous}{previous=$0}END{print}'
在你的例子中:
$> echo 'john paul
george
john paul
12
john paul' |awk '!(/^[a-zA-W]+$/ && previous ~/^john paul$/){print previous}{previous=$0}END{print}'
george
john paul
12
john paul
如果行中有一些数字,则打印前一个,否则不打印:
$> echo 'john paul
george 234
john paul
auie
john paul' |awk '!(/^[a-zA-W]+$/ && previous ~/^john paul$/){print previous}{previous=$0}END{print}'
john paul
george 234
auie
john paul
答案 4 :(得分:1)
sed 解决方案很简短:两个命令和大量注释;)
/john paul/ {
# read the next line and append to pattern space
N
# and then if we find "george" in that next line,
# only retain the last line in the pattern space
s/.*\n\(.*george\)/\1/
# and finally print the pattern space,
# as we don't use the -n option
}
您将上述内容放在某个sedscript
文件中,然后运行:
sed -f sedscript your_input_file
答案 5 :(得分:0)
您可能需要将\ r \ n更改为\ n或更改为\ r \ n,除此之外应该有效:
<?php
$string = "john paul
george
john paul
12
john paul";
$string = preg_replace("#john paul\r\n(george)#i",'$1',$string);
echo $string;
?>
您还可以将文件读入变量,然后覆盖文件。
答案 6 :(得分:0)
使用GNU awk进行多字符RS:
$ gawk -vRS='^$' '{gsub(/john paul\ngeorge/,"george")}1' file
george
john paul
12
john paul
或者如果每行上的内容比您的示例输入更多,则只需将RE更改为适合并使用gensub():
$ gawk -vRS='^$' '{$0 = gensub(/[^\n]*john paul[^\n]*\n([^\n]*george[^\n]*)/,"\\1","")}1' file
george
john paul
12
john paul
答案 7 :(得分:0)
只是将一些Perl扔进混音:
perl -ne 'print $p unless /george/ && $p =~ /john paul/; $p = $_ }{ print $p' file
打印上一行,除非当前行与/george/
匹配且上一行$p
与/john paul/
匹配。将$p
设置为上一行的值。 }{
有效地创建了一个END
块,因此在读取文件后也会打印最后一行。