1
necomancer 2019-03-08 11:38:51 +08:00 1
你可能需要 look 命令:
man look: look - display lines beginning with a given string 建议你看看手册。另外,先排序 B 文件会提高很多效率: sort -d B > Bsorted while read line do look ${line} Bsorted >> C done < A 希望你的 A,B 都是 unique 的,重复内容浪费资源。 至于 sort 和 uniq,都有比较快的方法,比如 linux 下还能用 parallel 加速。 |
2
necomancer 2019-03-08 11:48:52 +08:00
或者使用 sgrep,我记得 sgrep 是需要排序好的文件的,用二分查找。
|
3
necomancer 2019-03-08 11:50:22 +08:00
look 也是 binary search,但只能查行头。看实际需求吧。
|
4
geelaw 2019-03-08 11:56:29 +08:00
因为你每次都要重新读一次 B 文件 - - 先存到内存里比较好,所以请换 PowerShell 或者脚本语言。
$b = {} # 大小写不敏感,要得到敏感版本,使用 [System.Collections.Generic.Dictionary[string,string]]::new() gc B | % { $b[$_.Substring(0, $_.IndexOf(' ') - 1)] = $_ } gc A | % { $b[$_] } | sc C |
5
hugee 2019-03-08 11:59:39 +08:00
@shuizhongyu10 建议把文本发出来,这样我们好测试代码执行速度。
|
6
necomancer 2019-03-08 12:05:43 +08:00
每次读文件是个问题,sort -d B > /tmp/Bsorted,如果可以放内存里的话^_^
|
7
Sherlocker 2019-03-08 12:26:27 +08:00 2
给个文本截图啊,如果分隔符都是空格应该一条 awk 命令搞定
awk 'NR==FNR{a[$1]=$0;next}NR>FNR{if($1 in a)print $0}' a b > c |
8
shuizhongyu10 OP @necomancer 感谢老哥 ,试了下你这种,速度差别不是很大 。最大瓶颈应该就是重复读入了 B 文件,我就是不知道怎么只读入一次
|
9
shuizhongyu10 OP @geelaw 老哥。你这是个什么语言,我都不会用
|
10
shuizhongyu10 OP 牛逼了老哥,你这个速度贼快。你这种应该就是解决了多次读入 B 文件的问题,nb !
|
11
shuizhongyu10 OP @Sherlocker 牛逼了老哥,你这个完美解决了多次读 B 的问题,A,B 文件都只读一次,速度贼快。
|
12
shuizhongyu10 OP @hugee 那我一会传网盘,放个链接?
|
13
zbinlin 2019-03-08 13:42:33 +08:00 1
awk 'BEGIN { while ( (getline line<"A") > 0 ) { hash[line] = 1 } } hash[$1] == 1 { print $0 }' B
|
14
mononite 2019-03-08 13:56:06 +08:00
A 和 B 都读取一次,先读 A 保存起来,再读 B 过滤,用 awk 处理很直接。
awk 'NR==FNR{a[$1];next}$1 in a' A B |
15
geelaw 2019-03-08 14:28:26 +08:00 1
@geelaw #4 这里应该改成 $b=@{} 然后 gc 需要调优,正确的代码
measure-command { $sz = gc b -read 16000 | measure | select -expand count $sz *= 2 * 16000 $b = [System.Collections.Generic.Dictionary[string,string]]::new($sz) gc b -read 16000 | % { foreach ($x in $_) { $b[$x.substring(0,$x.indexof(' '))] = $x } } gc a -read 16000 | % { foreach ($x in $_) { $b[$_] } } | sc C -encoding utf8 } 需要 2 min 左右。 不过更好的方法是把 a 存进内存,然后 stream 处理 b,如下 measure-command { $s = [System.Collections.Generic.HashSet[string]]::new([string[]](gc a)) gc b -read 16000 | % { foreach ($x in $_) { if ($s.contains($x.substring(0,$x.indexof(' ')))) { $x } } } | sc C -encoding utf8 } 只要 12.5s 。 @shuizhongyu10 #9 答案在 #4 第一行 |
16
hanxiV2EX 2019-03-08 14:34:29 +08:00 via Android
我只会 sort 之后,再 diff。awk 还是不够熟练。
|
17
rrfeng 2019-03-08 14:34:32 +08:00 via Android
不是 join 吗?
|
18
shuizhongyu10 OP @geelaw 感谢感谢 PowerShell 有机会的话去学一下,目前采用的 awk 方法完全满足了需求。
测了下时间,只要 2.3s ,哈哈。 |
19
necomancer 2019-03-08 16:48:11 +08:00
@shuizhongyu10 你是 Linux 系统吗?我这边下文件不是很方便,Linux 下百度网盘神马的太不友好了 T_T,你有没有试试把 A Bsorted 文件都放在 /tmp 下? 一般发行版默认 /tmp 挂载一半内存大小。我也想知道一下效率~
|
20
coolloves 2019-03-08 16:57:48 +08:00 1
@necomancer 试试 baidupcs_go,可以跑满速,我刚下完,渣移动,100M 带宽,10MB 左右速度,差不多跑满了
|
21
shuizhongyu10 OP @necomancer
while read line do look ${line} Bsorted >> C done < A 我用上面你提供的这个方法,测了这样输出 100 条所用的时间,不知道你要的是不是这个。 放在硬盘和内存里都是 29s 左右。 我系统是 ubuntu,/tmp 并没有挂载在内存上,我通过 mount -t tmpfs -o size=300m tmpfs dir 挂了一块内存来测的。 按道理来说放在内存里应该有提升,不知道是测试的量太小还是哪里出了问题? |
22
hugee 2019-03-08 18:04:26 +08:00
@shuizhongyu10 可以的。然后你说下你的执行时间大概是多少,如果我弄出来效率有提高就告知你。
|
23
zclHIT 2019-03-08 18:42:26 +08:00 via iPhone
|
24
zclHIT 2019-03-08 18:43:01 +08:00 via iPhone
上面的链接应该就是你要做的吧?
|
25
necomancer 2019-03-08 19:16:55 +08:00
@shuizhongyu10 我没处理过那么大量的 A,频繁打开文件确实是瓶颈,无论文件是否在内存里。刚才搜到一个帖子,看到使用 wile read line 本身就是一个很低效的办法,看来 shell 的确不适合直接做这种事...
https://unix.stackexchange.com/questions/169716/why-is-using-a-shell-loop-to-process-text-considered-bad-practice ...😔 |
26
zclHIT 2019-04-15 11:23:01 +08:00
过去了一个月,问个新的问题,反过来要查找文件 a 中所有行,在文件 b 中没有的打印出来到文件 c 应该怎么写呢?
|