我有一个包含以下数据的文件:
当我找到匹配789时,我想删除上面两行(123和456)。是否可以使用sed或awk进行操作?请帮忙
答案 0 :(得分:3)
使用ed
,标准编辑器:
ed -s file <<< $'3,$g/789/-2,.d\nw'
ed
会看到以下命令:
3,$g/789/-2,.d
w
说明:
3,$g/789/
会将第3行 * 中的所有行标记到与/789/
匹配的文件末尾;然后,对于每个标记的行,它将执行命令:
-2,.d
表示:删除范围-2,.
,即在当前一行(-2
)上方开始两行的范围,并在此处结束(.
)。
然后w
表示写入文件。如果您想首先尝试而不写入文件,而是在终端上打印(出于测试目的),请将w
命令替换为,p
和Q
,如下所示:
ed -s file <<< $'3,$g/789/-2,.d\n,p\nQ'
请注意。 ed
确实编辑了文件(它是一个编辑器),所以它会愉快地保留符号链接和权限,这与所有其他依赖适用于流的工具的方法不同(sed
和awk
)
请注意。如果您的模式出现在前两行中,它将被保留(但是,这可以通过添加一些额外的命令来处理);如果你的模式出现在2行的范围内,你可能会有一些惊喜,例如,
000
123
456
789
123
789
将产生一个空文件,
123
456
789
123
789
你会收到错误。
* 范围从第3行开始,只是为了防止错误,以防你的模式出现在前两行
答案 1 :(得分:1)
此脚本不会将整个文件加载到内存中,这与其他一些答案不同,因此它对大文件有效,并假设您至少有3行
#n
1{
N
h
n
:loop
${
/789/! {
x
p
g
}
p
}
$!{
H
g
P
s/^[^\n]*\n//
h
n
b loop
}
}
如果将其保存为s.sed,则可以运行
sed -f s.sed file
如果最后一行与789匹配,它将删除最后一行之前的两行。
输入:
123
456
789
输出:
789
输入:
abc
123
456
789
输出:
abc
789
输入:
123
456
abc
输出:
123
456
abc
<强>解释强>
#n
会抑制正常输出。在与1
匹配的第一行,我们在N
附加下一行,并将其复制到保留空间h
。然后我们使用n
转到下一行,然后启动:loop
。
如果当前行是由$
获取的最后一行,那么我们检查它是否与789不匹配,在这种情况下,我们交换模式并使用x
保留空格,使用p
打印出新的模式空间,然后使用g
将保留空间复制到模式空间。最后我们打印出最后一行。
如果当前行不是最后一行。我们使用H
将当前行附加到保留空间,然后将保留空间复制到模式空间。我们使用P
打印图案空间的第一行,然后使用s/^[^\n]*\n//
删除第一行。我们将其复制回保留空间,转到下一行,然后使用b loop
重复循环。
答案 2 :(得分:1)
这可能适合你(GNU sed):
sed ':a;N;s/\n/&/2;Ta;/\n789$/s/.*\n//;P;D' file
在图案空间中保持3行的移动窗口,如果第3行是所需图案,则删除前两行。
答案 3 :(得分:0)
将文件加载到内存中(因此不适用于大文件)
sed '1h;1!H;$!d
x;/\n[0-9]\{1,\}\.[[:space:]]\{1,\}789$/ s/\(\(\n\)[[:alnum:][:blank:][:punct:]]*\)\{3\}$/\2789/
' YourFile
将文件加载到内存中,检查最后一行是否匹配,如果是,则删除上一行2,打印结果
答案 4 :(得分:0)
要求救援!
awk '{a[NR]=$0} END{for(i=1;i<=NR;i++) if(a[i+1] a[i+2]!~/789/) print a[i]}' test.1
输入(test.1)
1. 123
2. 456
3. 789
4. 012
5. 345
6. 678
7. 901
8. 789
9. 111
输出
3. 789
4. 012
5. 345
8. 789
9. 111