我想通过提取重要的联系电话来处理包含学生信息的巨大文本文件。
情景:
我在students.txt中有学生记录(> 100万)。在此文件(每行)中
等等
students.txt
1000000001A9234567890XXX5782463562...
1000000002B9325788532YYY...
1000000001C9234567890XXX6478542698XDE4578954568...
.
.
.
10010000008Z766443367ZZZ...
我想根据成绩
提取联系电话A级 - 提取字符12至21 - 手机号码(长度10)和字符25至34 - 家庭电话号码(长度10)
B级 - 仅提取手机号码第12至21号字符 - 手机号码(长度为10)
C级 - 提取字符12至21 - 手机号码(长度10)和字符25至34 - 家庭电话号码和字符38至47 - 办公室电话号码(长度10)
不要为其他年级提取任何东西。
我希望将提取的输出放在一个具有唯一联系号
的文件中 输出:important_contacts.txt
9234567890
5782463562
9325788532
6478542698
4578954568
有人可以帮我解决这个问题吗?
注意:每个 students.txt 包含超过 250万条记录
答案 0 :(得分:0)
这是如何做到这一点:
echo '1000000001A9234567890XXX5782463562...
1000000002B9325788532YYY...
1000000001C9234567890XXX6478542698XDE4578954568... ' | sed -n -r 's/[0-9]{10}A([0-9]{9}).*/\1/p'
923456789
或使用文件:
sed -n -r 's/[0-9]{10}A([0-9]{9}).*/\1/p' file > gradeA.txt
每个Grade编写一个这样的程序来提取和输出到不同的文件。
百万行不是sed的问题。
答案 1 :(得分:0)
您可以传递输入文件" students.txt"到shell脚本,它逐行读取记录并根据等级解析数据。然后通过shell参数扩展' $'。
提取你想要的子串如果不了解特定数据集的确切性质,请考虑以下输入文件 students.txt :
StudentID123GradeAPhonenumber123
StudentID456GradeBPhonenumber456
StudentID789GradeCPhonenumber789
StudentID321GradeAPhonenumber312
StudentID654GradeBPhonenumber654
StudentID987GradeCPhonenumber987
此脚本 parse_grades.sh :
#!/bin/sh
while read -r line; do
# save a line
PERSON=$line
# extract the grade
GRADE=${PERSON:17:1}
# and now process it
if [ "$GRADE" = "A" ]; then
# show student ID and grade
DATA_GRADE_A=${PERSON:0:18}
echo $DATA_GRADE_A >> outputfile.txt
fi
if [ "$GRADE" = "B" ]; then
# only show phone number
DATA_GRADE_B=${PERSON:18:14}
echo $DATA_GRADE_B >> outputfile.txt
fi
if [ "$GRADE" = "C" ]; then
# show StudentID and PhoneNo
SID=${PERSON:0:12}
PHONENO=${PERSON:18:14}
DATA_GRADE_C=$SID$PHONENO
echo $DATA_GRADE_C >> outputfile.txt
fi
done < "$1"
exit 0
使用以下命令使脚本可执行:
chmod +x parse_grades.sh
并将输入文件传递给它:
parse_grades.sh students.txt
根据以上记录集,您应该在outputfile.txt中获得以下结果:
StudentID123GradeA
Phonenumber456
StudentID789Phonenumber789
StudentID321GradeA
Phonenumber654
StudentID987Phonenumber987
脚本的核心思想是使用$ {VAR:Offset:Length}
现在您需要做的就是根据您的具体要求调整数字。
检查
man bash
或本网站了解更多信息
答案 2 :(得分:0)
使用 GNU awk
,您可以使用内置的FIELDWIDTHS
变量从固定宽度数据中提取字段值。以下单行执行您想要的任务:
awk 'BEGIN { FIELDWIDTHS = "10 1 10 3 10 3 10" } { if ($2 == "A") print $3 ORS $5; else if ($2 == "B") print $3; else if ($2 == "C") print $3 ORS $5 ORS $7; }' students-3M.txt > numbers.txt
您可以提供以空格分隔的数字,指定记录中每个字段的宽度:FIELDWIDTHS = "10 1 10 3 10 3 10"
。
我们在读取任何输入记录之前在BEGIN
规则中执行此操作。
然后,可以使用if else if
构造根据您的规则打印所需的字段(列)。
对于在新行上需要多个电话号码的成绩,我们使用内置输出记录分隔符ORS
打印我们的字段,默认情况下这是新行。
您可以将以下脚本保存到文件中,例如get-contacts.awk
BEGIN { FIELDWIDTHS = "10 1 10 3 10 3 10" }
{
if ($2 == "A") {
print $3 ORS $5
} else if ($2 == "B") {
print $3
} else if ($2 == "C") {
print $3 ORS $5 ORS $7
}
}
并致电:
awk -f get-contacts.awk students-3M.txt > numbers.txt
我使用以下php
脚本生成了3M行 测试数据 :
<?php
for ($i=0; $i < 3000000; $i++) {
$gr = strtoupper(substr(md5(microtime()),rand(0,26),1));
$pn = rand(1,9999999999);
$hn = rand(1,9999999999);
$on = rand(1,9999999999);
printf("100%07d%s%010dXXX%010dXDE%010d\n",$i,$gr,$pn,$hn,$on);
}