Chinaunix
标题: 提取行中不同的字符串的行 [打印本页]
作者: bmne 时间: 2017-05-16 20:19
标题: 提取行中不同的字符串的行
共四列,
要求:提取行中(各列中)不同的字符串的行
1 2 3 4
a b c d
1 1 1 1
1 1 2 2
1 1 2 3
1 2 3 3
1 2 3 1
1 2 2 3
1 2 3 3
1 1 1 2
1 2 2 2
输出
1 2 3 4
a b c d
请给个效率稍高一点的命令
这个有点慢
awk '($1!=$2&&$1!=$3&&$1!=$4&&$2!=$3&&$2!=$4&&$3!=$4)'
谢谢
作者: baby_神 时间: 2017-05-16 20:34
本帖最后由 baby_神 于 2017-05-16 20:36 编辑
awk '{for(i=1;i<=NF;i++)a[$i];if(length(a)==NF)print $0;delete a}' file
作者: sunzhiguolu 时间: 2017-05-16 20:53
- import io.Source
- for(s <- Source.fromFile(args(0)).getLines){
- val lst = s.split(raw"\s+")
- if(lst.length == lst.distinct.length) println(s)
- }
复制代码
作者: baby_神 时间: 2017-05-16 20:57
py版本
- a = """
- 1 2 3 4
- a b c d
- 1 1 1 1
- 1 1 2 2
- 1 1 2 3
- 1 2 3 3
- 1 2 3 1
- 1 2 2 3
- 1 2 3 3
- 1 1 1 2
- 1 2 2 2
- """
- for i in a.split("\n"):
- if len(set(i)) == 5:
- print(i)
复制代码
作者: haooooaaa 时间: 2017-05-16 21:18
- awk '!a[$1]++&&!b[$2]++&&!c[$3]++&&!d[$4]++'
复制代码
作者: 799029078 时间: 2017-05-16 21:39
厉害了
作者: bmne 时间: 2017-05-17 06:34
回复 2# baby_神
还行。比我一楼的要稍快一点点。
谢谢,辛苦
real 42m43.830s
user 42m16.700s
sys 0m9.750s
作者: bmne 时间: 2017-05-17 06:41
本帖最后由 bmne 于 2017-05-17 06:53 编辑
回复 5# haooooaaa
大牛,我试了小文件,没问题。
但,换成大文件后,运行6分多钟就结束运行了,但没出最终输出结果(输出结果不正确)。反复几次都这样,我没找到原因
real 6m12.323s
user 6m4.730s
sys 0m3.291s
作者: 关阴月飞 时间: 2017-05-17 08:40
回复 5# haooooaaa
这个作用域太广了,全文本范围去重,本意应该是以行去重就行
作者: blackold 时间: 2017-05-17 09:10
一定要awk?
try:
- sed '/\<\(.*\)\>.*\<\1\>/d;' urfile
复制代码
- grep -Ev '\<(.*)\>.*\<\1\>' urfile
复制代码
作者: blackold 时间: 2017-05-17 09:11
本帖最后由 blackold 于 2017-05-17 09:45 编辑
发重了。
awk 居然不支持后引用,太烂了,不要用它了。
作者: bmne 时间: 2017-05-17 13:39
回复 10# blackold
大牛好
你太忙,没想到有时间出手。谢谢
实话实说。这两个命令效率慢的吓人。实战中运行结束要5个多小时(估计)。运行途中让我停止了
我没想到grep也会这么慢
作者: 本友会机友会摄友会 时间: 2017-05-17 15:23
提示: 作者被禁止或删除 内容自动屏蔽
作者: bmne 时间: 2017-05-17 17:50
本帖最后由 bmne 于 2017-05-17 17:56 编辑
回复 10# blackold
大牛
我这次的实战样本是 (每一行中)纯字母+空格,没有其它,就是稍大些(近15GB)。每一组字符串最长超不过7个字符。换言之,极端情况每一行最多共30个字符。
我运行前先dos2unix 然后 我前面必须LANG=C再运行。因我以前吃过亏,我已长记性。总之,前期该做的工作已准备好
然后,再运行你的命令的。同等条件下目前较理想的是1、2楼的awk 运行时间估计你也看到了
如果有点时间,麻烦你看看grep的那个(我自己认为它应该效率高些)。如果太忙,就到此吧。我凑合着用awk即可
不好意思
作者: blackold 时间: 2017-05-18 08:32
回复 15# bmne
对的。
要效率的话,最好不用正则。正则本身就是循环,尤其是后引用。
作者: dahe_1984 时间: 2017-05-18 10:37
行中(各列中)不同?
题目啥意思?我咋没看懂呢?
行不同,列也不同?
作者: bmne 时间: 2017-05-18 11:05
回复 17# dahe_1984
每一行的不同,各个字符串的不同
因为中间有空格,所以我括号说明了一下,同一行中的各列的不同
若再没看明白,就看看列举的数据
作者: 本友会机友会摄友会 时间: 2017-05-18 12:54
提示: 作者被禁止或删除 内容自动屏蔽
作者: bmne 时间: 2017-05-18 14:02
本帖最后由 bmne 于 2017-05-18 15:12 编辑
回复 19# 本友会机友会摄友会
知道你用心了,大牛级人物,也浪费脑细胞了。谢谢,辛苦了
老师只告诉我去买一瓶醋,突然半路遇到一个熟人,非要让我再买瓶酱油,可我没带钱。 不好意思,开个玩笑
(另,若非要让我说实话, @jason680 对这方面shell研究深)
作者: dahe_1984 时间: 2017-05-18 14:22
回复 7# bmne
$ time perl find.pl
1 2 3 4
a b c d
real 0m0.261s
user 0m0.031s
sys 0m0.030s
作者: dahe_1984 时间: 2017-05-18 14:23
$ time perl find.pl
1 2 3 4
a b c d
real 0m0.261s
user 0m0.031s
sys 0m0.030s
发给你测试的数据呗。
作者: bmne 时间: 2017-05-18 14:29
回复 21# dahe_1984
不好意思。我帖子里面标注的时间,是实战的结果。不是我一楼数据的
作者: dahe_1984 时间: 2017-05-18 14:34
回复 23# bmne
实战数据发下呗,正好我闲着没事,自己搞搞
作者: bmne 时间: 2017-05-18 14:38
回复 24# dahe_1984
太大了。给不了你(15GB)
你试一下2楼的命令。这是我测的
real 0m0.016s
user 0m0.000s
sys 0m0.015s
作者: dahe_1984 时间: 2017-05-18 14:39
回复 25# bmne
切1G或者几百M,数据太小看不出什么
作者: dahe_1984 时间: 2017-05-18 14:42
nxf26935@star:~$ time perl find.pl
1 2 3 4
a b c d
real 0m0.005s
user 0m0.000s
sys 0m0.004s
作者: dahe_1984 时间: 2017-05-18 14:42
服务器上跑的
作者: bmne 时间: 2017-05-18 14:44
回复 26# dahe_1984
请放出你的手中的命令来可以?看看杀手锏
谢谢
作者: dahe_1984 时间: 2017-05-18 14:47
抓图如上,
-
Capture.GIF
(4.34 KB, 下载次数: 0)
作者: dahe_1984 时间: 2017-05-18 14:49
这里的附件怎么上传才能看到?
-
Capture.GIF
(4.34 KB, 下载次数: 18)
作者: dahe_1984 时间: 2017-05-18 15:05
#perl!
use strict;
while(<DATA>){
my @tmpArr;
my $flag = 1;
my @found = "";
@tmpArr = split(/\s+/,$_);
foreach (@tmpArr) {
if("@found" =~ $_)
{
$flag = 0;
next;
} else {
push(@found, $_);
}
}
if($flag == 1) {
printf "@found\n";
@found = "";
}
}
__DATA__
1 2 3 4
a b c d
1 1 1 1
1 1 2 2
1 1 2 3
1 2 3 3
1 2 3 1
1 2 2 3
1 2 3 3
1 1 1 2
1 2 2 2
作者: dahe_1984 时间: 2017-05-18 15:06
估计只判断自身而不push新的数组会更快一些。
作者: bmne 时间: 2017-05-18 15:09
回复 33# dahe_1984
谢谢,辛苦
作者: 本友会机友会摄友会 时间: 2017-05-18 17:40
提示: 作者被禁止或删除 内容自动屏蔽
作者: elu_ligao 时间: 2017-05-19 11:18
本帖最后由 elu_ligao 于 2017-05-19 11:22 编辑
试试这个
- awk '{for(i=1;i<=NF;++i)if(a[$i]++)next; delete a}1' file
复制代码
作者: elu_ligao 时间: 2017-05-19 11:23
编辑没用, 应该
awk '{delete a; for(i=1;i<=NF;++i)if(a[$i]++)next}1'
作者: bmne 时间: 2017-05-19 14:16
回复 37# elu_ligao
谢谢,谢谢。辛苦
大牛出手,招招带杀气
时间短的是我的1楼数据,时间长的是实战数据。另,时间长的估计不准,因为我同时在干别的事情中
-
1.jpg
(22.15 KB, 下载次数: 23)
作者: me09 时间: 2017-05-25 17:27
回复 8# bmne
大概是用的列统计太多了 修改下:
- awk '!a[$1]++&&!b[$2]&&!c[$3]&&!d[$4]'
复制代码
作者: me09 时间: 2017-05-25 17:28
回复 8# bmne
大概是用的列统计太多了 修改下:
- awk '!a[$1]++&&!b[$2]&&!c[$3]&&!d[$4]'
复制代码
作者: me09 时间: 2017-05-25 17:28
回复 8# bmne
awk '!a[$1]++&&!b[$2]&&!c[$3]&&!d[$4]'
作者: me09 时间: 2017-05-25 17:58
回复 8# bmne
awk '!a[$1]++&&!b[$2]&&!c[$3]&&!d[$4]'
作者: me09 时间: 2017-05-28 07:21
本帖最后由 me09 于 2017-05-28 07:34 编辑
awk '{for(i=1;i<=NF;++i)if(a[$i]++)next; delete a}1' file 这个逻辑 和 awk '!a[$1]++&&!b[$2]++&&!c[$3]++&&!d[$4]++' 类似
作者: me09 时间: 2017-05-28 09:52
本帖最后由 me09 于 2017-05-28 11:54 编辑
这个看起来有点费劲:执行流程解释
1:delete a,释放 a;
2:for{i=1;i<=NF;i++} 行循环 具体到文本 就是 1 2 3 4的去遍历,i=1 对应域 $1,i=2 对应域 $2....:NF 是域数目,本行有4个域 NF=4
3:if(a[$i]++) next;这句是亮点,如果a[$i] ++为真 则next;跳过,也就是本行的遍历就此结束,不会走到最后的输出{ ...}1的部分
把脚本修改一个演示方式 就会比较容易理解:
awk '{delete a;for (i=1;i<=NF;i++) if(a[$i]++){print "next"}else{print "continue"}}1' c1
continue
continue
continue
continue
1 2 3 4
continue
continue
continue
continue
a b c d
continue
next
next
next
1 1 1 1
continue
next
continue
continue2 2 3 4
continue
continue
continue
continue
2 3 4 5
这么看就会比较容易理解这个判断的next;语句的用途, 只要行判断过程中出现一次next语句为真的输出,那么就会跳过这行,进入下一行的条件判断和执行,被跳过的行就不会有输出,因为执行不到{...}1的阶段,被next跳过了次行后续的执行动作。
4:{}1
awk ‘{code}1’ 中的“1”是干什么的?
一个完整的awk语句为:Awk ‘[patten]{action}……’, 其中pattern缺省为1,action缺省为{print}。
那么awk ‘1’完整的写法就是awk ‘1{print}’; 同理,awk ‘{print}’完整的写法也是awk ‘1{print}’。
作者: bmne 时间: 2017-05-28 10:08
回复 44# me09
谢谢,辛苦
一直关注你的帮助
欢迎光临 Chinaunix (http://bbs.chinaunix.net/) |
Powered by Discuz! X3.2 |