我有一个包含大量数据的数据集:
ID Number: A00001
Name: John Smith
Address: 123 Any Street
City: AnyTown
State: Ohio
Zip: 12345
ID Number: A00002
Name: Jane Doe
Address: 123 Any Street
City: AnyTown
State: Nebraska
Zip: 12346
ID Number: C00003
Name: Jim Shields
Address: 123 Any Street
City: AnyTown
State: Alaska
Zip: 12347
ID Number: D11111
Name: Mary Ellis
Address: 123 Any Street
City: AnyTown
State: Nevada
Zip: 12348
我想提取数据并将其分开,如下所示:
ID Number: A00001
Name: John Smith
Zip: 12345
=========================
ID Number: A00002
Name: Jane Doe
Zip: 12346
=========================
ID Number: C00003
Name: Jim Shields
Zip: 12347
=========================
ID Number: D11111
Name: Mary Ellis
Zip: 12348
=========================
我已经尝试了我能找到的每个 grep 和 egrep 选项,但我能得到的最接近的是在每行输出之间放置一个空行(新行)。
答案1
grep
是一个模式匹配工具,而不是文本重新格式化工具。使用诸如sed
, awk
, 或 之类的东西perl
代替。例如:
$ awk '/^(ID Number|Name|Zip):/;
/^[[:blank:]]*$/ { print "=========================" }'
ID Number: A00001
Name: John Smith
Zip: 12345
=========================
ID Number: A00002
Name: Jane Doe
Zip: 12346
=========================
ID Number: C00003
Name: Jim Shields
Zip: 12347
=========================
ID Number: D11111
Name: Mary Ellis
Zip: 12348
这[[:blank:]]*
匹配任何行看就像它们是空的,但实际上包含水平空间,例如空格或制表符......这比您想象的更常见,因为它是仅用您的眼睛很难看到的东西。
或者,使用 perl:
perl -l -n -e 'print if /^(ID Number|Name|Zip):/;
print "=" x 25 if /^\h*$/' input.txt
或与sed
.首先,如果您有 GNU sed 或其他一些能够理解 Perl RE 的\h
“水平空间”的 sed:
sed -n -E -e '/^(ID Number|Name|Zip):/p; s/^\h*$/=========================/p' input.txt
否则,使用任何 sed:
sed -n -E -e '/^(ID Number|Name|Zip):/p; s/^[[:blank:]]*$/=========================/p' input.txt
答案2
在每个 Unix 机器上的任何 shell 中使用任何 awk:
$ cat tst.awk
BEGIN {
FS = ":"
split(tgts,tmp)
for (i in tmp) {
tags[tmp[i]]
}
sep = "========================="
}
$1 in tags
!NF { print sep }
END { if (NF) print sep }
$ awk -v tgts='ID Number:Name:Zip' -f tst.awk file
ID Number: A00001
Name: John Smith
Zip: 12345
=========================
ID Number: A00002
Name: Jane Doe
Zip: 12346
=========================
ID Number: C00003
Name: Jim Shields
Zip: 12347
=========================
ID Number: D11111
Name: Mary Ellis
Zip: 12348
=========================
$ awk -v tgts='City:State' -f tst.awk file
City: AnyTown
State: Ohio
=========================
City: AnyTown
State: Nebraska
=========================
City: AnyTown
State: Alaska
=========================
City: AnyTown
State: Nevada
=========================
答案3
将每个部分视为一条记录,并将部分中的每一行视为一个字段,似乎您想要输出每个记录的前两个和最后一个字段,并用一行等号来分隔输出中的记录。
$ awk -F'\n' -v OFS='\n' -v RS='' -v ORS='\n=========================\n' '{ print $1,$2,$NF }' file
ID Number: A00001
Name: John Smith
Zip: 12345
=========================
ID Number: A00002
Name: Jane Doe
Zip: 12346
=========================
ID Number: C00003
Name: Jim Shields
Zip: 12347
=========================
ID Number: D11111
Name: Mary Ellis
Zip: 12348
=========================
命令行首先将输入和输出字段分隔符的值设置为换行符。这样做可以确保字段在输入和输出中都是单独的行。
然后将记录分隔符设置为空字符串,这将启用“段落模式”,即,它使我们能够将由一个或多个空行分隔的一段文本读取为单个记录。
然后将输出记录分隔符设置为等号,并在两端添加换行符。
实际代码打印每条记录的第一个、第二个和最后一个字段。您也可以使用$6
代替$NF
.