我有一个 CSV 文件users.csv
,其中包含用户名、用户 ID 和其他数据的列表:
username, userid, sidebar_side, sidebar_colour
"John Lennon", 90123412, "left", "blue"
"Paul McCartny", 30923833, "left", "black"
"Ringo Starr", 77392318, "right", "blue"
"George Harrison", 72349482, "left", "green"
在另一个文件中,toremove.txt
我有一个用户 ID 列表:
30923833
77392318
users.csv
有没有一种聪明、有效的方法来从文件中删除包含 ID 的所有行toremove.txt
?我编写了一个简单的Python应用程序来解析这两个文件,并仅将那些在 中找不到的行写入新文件toremove.txt
,但速度非常慢。也许一些sed
魔法awk
可以在这里提供帮助?
考虑到上面的例子,这是期望的结果:
username, userid, sidebar_side, sidebar_colour
"John Lennon", 90123412, "left", "blue"
"George Harrison", 72349482, "left", "green"
答案1
使用grep
,您可以执行以下操作:
$ grep -vwF -f toremove.txt users.txt
username, userid, sidebar_side, sidebar_colour
"John Lennon", 90123412, "left", "blue"
"George Harrison", 72349482, "left", "green"
和awk
:
$ awk -F'[ ,]' 'FNR==NR{a[$1];next} !($4 in a)' toremove.txt users.txt
username, userid, sidebar_side, sidebar_colour
"John Lennon", 90123412, "left", "blue"
"George Harrison", 72349482, "left", "green"
答案2
这是 Gnouc 的awk
答案,修改为空间盲:
awk -F, 'FNR==NR{a[$1];next} !(gensub("^ *","",1,$2) in a)' toremove.txt users.csv
因为它只使用逗号(而不是空格)作为分隔符,
$1
所以"John Lennon"
我们$2
在 90123412
检查 它(用户 ID)是否在文件中之前gensub
删除任意数量的前导空格。$2
toremove.txt
答案3
好的 ruby 方式:如果你在一个文件中有一个字符串列表,并且你想从另一个文件中删除所有行,甚至包含第一个文件中的任何字符串(在本例中从“file1”中删除“file2”)ruby 文件:
b=File.read("file2").split # subtract this one out
remove_regex = Regexp.new(b.join('|'))
File.open("file1", "r").each_line do |line|
if line !~ remove_regex
puts line
end
end
不幸的是,对于一个大的“要删除”文件,这似乎将复杂性降低到 O(N^2) (我的假设是正则表达式有很多工作要做),但仍然可能对那里的人有用(如果你想要的不仅仅是删除整行)。在某些情况下可能会更快。
如果您追求速度,另一个选择是使用相同的哈希检查机制,但要仔细“解析”该行以查找可能匹配的字符串,然后将它们与您的哈希进行比较。
在 ruby 中,可能看起来像这样:
b=File.read("file2").split # subtract this one out
hash={}
for line in b
hash[line] = 1
end
ARGF.each_line do |line|
ok = true
for number in line.scan(/\d{9}/)
if hash.key? number
ok=false
end
end
if (ok)
puts line
end
end
另请参阅 Scott 的答案,它与此处提出的 awk 答案类似,并且避免了 O(N^2) 复杂性(唷)。