users.csv
userNames, userID 및 기타 데이터 목록 이있는 CSV 파일 이 있습니다.
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
에는 userID 목록이 있습니다.
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"
답변
을 사용 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"
답변
Gnouc의 awk
대답은 공간 맹인으로 수정되었습니다.
awk -F, 'FNR==NR{a[$1];next} !(gensub("^ *","",1,$2) in a)' toremove.txt users.csv
쉼표 (공백이 아닌) 만 구분 기호,
$1
is "John Lennon"
, $2
is 90123412
(선행 공백 포함) 등으로 사용 gensub
하기 $2
때문에 toremove.txt
파일 에 사용자 이름이 있는지 여부를 확인하기 전에 여러 개의 선행 공백을 제거하는 데 사용 합니다.
답변
루비 방식으로 확인 : 파일에 문자열 목록이 있고 첫 번째 파일에 문자열이 포함 된 다른 파일에서 모든 줄을 제거하려는 경우 (이 경우 “file1″에서 “file2″제거) 루비 파일 :
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)로 저하시키는 것처럼 보입니다 (제 생각에는 정규 표현식에 많은 작업이 필요합니다). 전체 줄을 제거하는 것 이상을 원합니다). 경우에 따라 더 빠를 수도 있습니다.
속도를 높이려는 또 다른 옵션은 동일한 해시 검사 메커니즘을 사용하지만 일치하는 문자열의 줄을 신중하게 “파싱”한 다음 해시와 비교하는 것입니다.
루비에서는 다음과 같이 보일 수 있습니다.
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) 복잡성을 피합니다.