users.csv
사용자 이름, 사용자 ID 및 기타 데이터 목록이 포함된 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
사용자 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
awk
공간맹을 위해 수정된 Gnouc의 답변은 다음과 같습니다 .
awk -F, 'FNR==NR{a[$1];next} !(gensub("^ *","",1,$2) in a)' toremove.txt users.csv
구분 기호로 공백이 아닌 쉼표만 사용하기 때문에 해당 공백 (사용자 ID)이 파일에 있는지 확인하기 전에 선행 공백을 제거합니다 $1
."John Lennon"
$2
90123412
gensub
$2
toremove.txt
답변3
좋은 루비 방식: 한 파일에 문자열 목록이 있고 다른 파일의 모든 줄을 삭제하려는 경우포함하다첫 번째 파일의 문자열(이 경우 "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)로 줄이는 것처럼 보이지만(내 가정은 정규 표현식이 수행할 작업이 많다고 가정함) 여전히 누군가에게는 유용할 수 있습니다(만약 전체 행을 삭제하는 것 이상의 것을 원합니다). 어떤 경우에는 더 빠를 수도 있습니다.
속도를 추구한다면 또 다른 옵션은 동일한 해시 검사 메커니즘을 사용하는 것입니다. 단, 일치하는 문자열이 있는지 라인을 주의 깊게 "구문 분석"한 다음 이를 해시와 비교합니다.
루비에서는 다음과 같이 보일 수 있습니다:
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
여기에 제안된 awk 답변과 유사하고 O(N^2) 복잡성(휴)을 피하는 Scott의 답변도 참조하세요.