如何从文件中提取以下字符串?

如何从文件中提取以下字符串?

考虑以下数据(假设位于 file.txt 中):

P 5 24 0 0 -9.0786328019999996e+02 9.1141809916739828e+02 8.0419002445999993e+01 22 0 0 -6 0
P 8 24 -3.9196518724924090e+00 2.0727804903086735e+00 -8.9632605571651516e+02 8.9993737237679568e+02 8.0419002445999993e+01 44 0 0 -65 0
P 88 24 -4.2389618700766505e+00 1.2238515466784179e+00 -8.9698474520778257e+02 9.0059331315537133e+02 8.0419002445999993e+01 62 0 0 -89 0
E 2 -1 -1.0000000000000000e+00 XXX
P 5 24 0 0 -6.7702324192000003e+02 6.8178272642703166e+02 8.0419002445999993e+01 22 0 0 -6 0
P 8 24 -5.6932512713246979e+01 4.6556691594912991e+01 -6.3984521745934762e+02 6.4905928450035572e+02 8.0419002445999993e+01 44 0 0 -9 0
E 3 -1 -1.0000000000000000e+00 -1.0000000000000000e+00 YY

即一般来说它具有以下形式

P ..
...
P ..
E ..
P ..
...
P ..
E ..

您能否告诉我是否可以制作一个仅包含P ..之前行的文件E ..

即文件与

P 88 24 -4.2389618700766505e+00 1.2238515466784179e+00 -8.9698474520778257e+02 9.0059331315537133e+02 8.0419002445999993e+01 62 0 0 -89 0
P 8 24 -5.6932512713246979e+01 4.6556691594912991e+01 -6.3984521745934762e+02 6.4905928450035572e+02 8.0419002445999993e+01 44 0 0 -9 0

答案1

使用grep(因为你用它标记了),并假设我们使用的工具实现具有非标准选项,-B用于提取匹配行以及一些前面的行:

$ grep -B 1 '^E' file.txt | grep '^P'
P 88 24 -4.2389618700766505e+00 1.2238515466784179e+00 -8.9698474520778257e+02 9.0059331315537133e+02 8.0419002445999993e+01 62 0 0 -89 0
P 8 24 -5.6932512713246979e+01 4.6556691594912991e+01 -6.3984521745934762e+02 6.4905928450035572e+02 8.0419002445999993e+01 44 0 0 -9 0

这使用了grep两次,首先提取所有以 开头的行E以及这些行之前的任何行,然后提取以P该行开头的行。

效果是您将得到以 开头的那些行,P后面紧接着是以 开头的行E

将第二个的输出重定向grep到文件以将其保存在某个文件中。


使用,记住变量中awk以 开头的任何行,并在看到以 开头的行时打印(并清除)它:PplineE

$ awk '/^P/ { pline = $0 } /^E/ && length(pline) > 0 { print pline; pline = "" }' file
P 88 24 -4.2389618700766505e+00 1.2238515466784179e+00 -8.9698474520778257e+02 9.0059331315537133e+02 8.0419002445999993e+01 62 0 0 -89 0
P 8 24 -5.6932512713246979e+01 4.6556691594912991e+01 -6.3984521745934762e+02 6.4905928450035572e+02 8.0419002445999993e+01 44 0 0 -9 0

使用sed并假设行仅单独出现,而不是在两个或多个连续行的组中出现(如果出现,您将获得每行输出一次的E最新行):PE

$ sed -e '/^P/ { h; d; }' -e 'g'  file
P 88 24 -4.2389618700766505e+00 1.2238515466784179e+00 -8.9698474520778257e+02 9.0059331315537133e+02 8.0419002445999993e+01 62 0 0 -89 0
P 8 24 -5.6932512713246979e+01 4.6556691594912991e+01 -6.3984521745934762e+02 6.4905928450035572e+02 8.0419002445999993e+01 44 0 0 -9 0

这会将任何P行保存到保留空间并立即开始下一个循环。如果该行不是一行,则从保留空间中取出P最近保存的行并输出。P

(基于相同的假设,awk上面的代码可以缩短为awk '/^P/ { pline = $0; next } { print pline }' file将代码直译sedawk

相关内容