我有一个非常大的文本文件(16GB),我希望尽可能快地进行子集化。 以下是涉及的数据样本
0 M 4 0
0 0 Q 0 10047345 3080290,4098689 50504886,4217515 9848058,1084315 50534229,4217515 50591618,4217515 26242582,2597528 34623075,3279130 68893581,5149883 50628761,4217517 32262001,3142702 35443881,3339757
0 108 C 0 50628761
0 1080 C 0 50628761
1 M 7 0
1 0 Q 0 17143989
2 M 15 1
2 0 Q 0 17143989 4219157,1841361,853923,1720163,1912374,1755325,4454730 65548702,4975721 197782,39086 54375043,4396765 31589696,3091097 6876504,851594 3374640,455375 13274885,1354902 31585771,3091016 61234218,4723345 31583582,3091014
2 27 C 0 31589696
每一行的第一个数字是 sessionID 以及任何一行' M'表示会话的开始(数据按会话分组)。 M后面的数字是 Day ,第二个数字是 userID ,用户可以有多个会话。
我想提取与特定用户相关的所有行,每个会话包括所有行,直到下一个' M'遇到行(可以是任意数量的行)。作为第二项任务,我还想提取与特定日期相关的所有会话行。
例如,对于上述数据,要提取用户ID' 0' 0的记录。输出将是:
0 M 4 0
0 0 Q 0 10047345 3080290,4098689 50504886,4217515 9848058,1084315 50534229,4217515 50591618,4217515 26242582,2597528 34623075,3279130 68893581,5149883 50628761,4217517 32262001,3142702 35443881,3339757
0 108 C 0 50628761
0 1080 C 0 50628761
1 M 7 0
1 0 Q 0 17143989
要提取第7天的记录,输出将是:
1 M 7 0
1 0 Q 0 17143989
我相信到目前为止我已经取得了一些更加优雅和简单的解决方案,并且获得一些反馈和建议会很棒。谢谢。
我尝试使用 pcrgrep -M 直接应用此模式(匹配两个M'之间的数据),但很难在整个换行符中使用它。我仍然怀疑这可能是最快的选择,所以关于这是否可行的任何指导都会很棒。
下一部分非常分散,如果您已经有了更好解决方案的想法,则没有必要继续阅读!
如果不能解决上述问题,我将问题分为两部分:
第1部分:隔离所有' M'行以获取属于该用户/日的会话列表
grep方法很快(然后需要弄清楚如何使用这些数据)
time grep -c "M\t.*\t$user_id" trainSample.txt >> sessions.txt
创建数组的awk方法很慢
time myarr=$(awk '/M\t.*\t$user_id/ {print $1}' trainSample.txt
第2部分:在第1部分中创建的列表中提取属于会话的所有行
继续使用awk方法,我为每个人运行grep,但这样做太慢了(完成16GB的天数)
for i in "${!myarr[@]}";
do
grep "^${myarr[$i]}\t" trainSample.txt >> sessions.txt
echo -ne "Session $i\r"
done
而不是像上面那样使用每个会话ID运行grep一次使用它们在一个grep命令中的速度要快得多(我用[1 | 2 | 3 | .. | 8]格式的8个sessionID运行它并且每个人分别花了相同的时间,即快了8倍)。但是,我需要弄清楚如何动态地执行此操作
我实际上已经建立了一个工作解决方案,只需要几秒钟就可以完成,但它是一些凌乱且不灵活的bash coe,我还没有扩展到第二个(隔离天数)的情况。
答案 0 :(得分:4)
我想提取与特定用户相关的所有行,每个会话包括所有行,直到遇到下一个“M”行(可以是任意数量的行)。
$ awk '$2=="M"{p=$4==0}p' file
0 M 4 0
0 0 Q 0 10047345 3080290,4098689 50504886,4217515 9848058,1084315 50534229,4217515 50591618,4217515 26242582,2597528 34623075,3279130 68893581,5149883 50628761,4217517 32262001,3142702 35443881,3339757
0 108 C 0 50628761
0 1080 C 0 50628761
1 M 7 0
1 0 Q 0 17143989
作为第二项任务,我还想提取与特定日期相关的所有会话行。
$ awk '$2=="M"{p=$3==7}p' file
1 M 7 0
1 0 Q 0 17143989