提取与关键字对应的家庭数据。
Z1/NEW "THE_PALM" 769 121003 1545
NEW HOUSE IN
SOMETHING SOMETHING
SN HOUSE CLASS
FIRST PSD93_PU 1579
CHAIRS
WOOD
SILVER SPOON
GREEN GARDEN
Z1/OLD "THE_ROSE" 786 121003 1343
NEW HOUSE OUT
SOMETHING NEW
SN HOUSE CLASS
FIRST_O PSD1000_ST 1432
CHAIRS
WOOD
GREEN GARDEN
BLACK PAINT
Z1/OLD "The_PURE" 126 121003 3097
NEW HOUSE IN
SOMETHING OLD
SN HOUSE CLASS
LAST_O JD4_GOLD 1076
CHAIRS
SILVER SPOON
我有一个非常大的文件。每个描述的末尾都有关于房子的项目清单。对应于包含SILVER SPOON
的房屋,我想提取HOUSE
ID,如数据PSD93_PU
和日期121003
。我尝试了以下方法:
awk 'c-->0;$0~s{if(b)for(c=b+1;c>1;c--)print r[(NR-c+1)%b];print;c=a}b{r[NR%b]=$0}' b=7 a=0 s="SILVER" infile > outfile
但问题是关键字SILVER
上方的行数是如此随机,我无法找出解决方案。
答案 0 :(得分:0)
假设每个新房子都以Z1
$ awk '$1 ~ /^Z1/ { date=$4; id=""; f=0; next; } \
$1 == "SN" { f=1; next; } \
f == 1 { id=$2; f=0; next; } \
$1" "$2 == "SILVER SPOON" { print id,date }' file
,在新房子上,重置所有变量并获取日期
如果 SN 匹配,则下一行包含id
从该行获取id
如果找到“ SILVER SPOON ”,则打印id
和date
如果没有找到,将会满足新房子,并重置变量。
使用给定数据进行测试:
$ awk '$1 ~ /^Z1/ { date=$4; id=""; f=0; next; } $1 == "SN" { f=1; next; } f == 1 { id=$2; f=0; next; } $1 == "SILVER SPOON" && $2 == "SPOON" { print id,date }' file
PSD93_PU 121003
JD4_GOLD 121003
note :
如果有人知道如何以及$1 == "SILVER" && $2 == "SPOON"
可以在一个声明中合并在一起,那就好了:) - 如:$1,$2 == "SILVER SPOON"
修改的:
可以使用$1" "$2 == "SILVER SPOON"
来完成
一个人可能会省略空格并执行$1$2 == "SILVERSPOON"
但即使$2
为空并且$1
包含整个字符串,或$1
SILVERSPO { em>和$2
ON 。所以这个空间就像是一场严格的匹配。
答案 1 :(得分:0)
使用sed:
sed -n -e 's/^Z1[^"]*"[^"]*"[ \t]*[0-9]*[ \t]*\([0-9]*\).*/\1/p'
-e '/^SN[ \t]*HOUSE/ { n; s/^[^ \t]*[ \t]*\([^ \t]*\).*/\1/p }'
首先,我们使用sed
选项调用-n
,以告诉它只打印我们告诉它的内容。
第一个命令将搜索特定模式以提取日期。该模式包括:
^Z1
:以字符串“Z1”开头的行。[^"]*
:零个或多个不是双引号的字符"
:双引号字符[^"]*
:零个或多个不是双引号的字符[ \t]*
:零个或多个字符为制表符或空格[0-9]*
:零个或多个数字[ \t]*
:零个或多个字符为制表符或空格\([0-9]*\)
:零个或多个数字。使用反斜括号来捕获匹配,即。匹配存储在辅助变量\1
中。.*
:零个或多个字符,有效地跳过所有字符,直到该行结束。然后将此匹配的行替换为\1
,其中包含我们捕获的内容:日期。命令后p
告诉sed打印结果。
第二行包含两个组合在一起的命令(在大括号内),因此它们仅在大括号之前的“地址”上执行。地址是一种模式,因此它在与模式匹配的每一行上执行。该模式由一行以“SN”开头,后跟一系列空格或制表符,后跟字符串“HOUSE”。
当模式匹配时,我们首先执行n
next命令,该命令从输入加载下一行。然后,我们从新行中提取ID,其方式类似于提取日期。匹配的替代模式是:
^[^ \t]*
:以零个或多个不是空格或制表符(空格)的字符开头的字符串。[ \t]*
:然后有一个零或多个空格和/或制表符的序列。\([^ \t]*\)
:然后捕获一系列非空白字符.*
:匹配剩余的字符,以便跳过它们。替换成为捕获的ID,我们再次告诉sed将其打印出来。
这将打印出包含日期的行,后面是包含ID的行。如果你想要一个格式为ID date
的行,你可以将sed的输出传递给另一个sed实例,如下所示:
sed -n -e [...] | sed -e 'h;n;G;s/\n/ /'
此sed实例执行以下操作:
h
命令告诉它将该行存储到保留空间(辅助缓冲区)。n
命令阅读下一行。G
get命令会将保留空间的内容追加到模式空间(工作缓冲区)中,所以现在我们有ID行后跟日期行。希望这有助于=)
答案 2 :(得分:0)
如果您的记录被两个或三个空白行分隔,并且家庭项目之前的行间距一致,您可以使用GNU awk
,如下所示:
awk -r 'BEGIN { RS="\n{3}\n*"; FS="\n" } /SILVER SPOON/ { split($1, one, OFS); split($6, two, OFS); print two[2], one[4] }' file.txt
结果:
PSD93_PU 121003
JD4_GOLD 121003