2017-05-03 8 views
2

텍스트 파일에 단어가 words.txt 인 단어가 있는데이 단어가 하위 폴더 및 파일이 포함 된 내 원본 폴더에 있는지 확인해야합니다. 폴더 내의 여러 단어를 확인하는 방법

나는이 코드를 사용하여 배열에 모든 단어를 얻을 수있었습니다 :

array_of_words = [] 

File.readlines('words.txt').map do |word| 
    array_of_words << word 
end 

을 그리고 나는 또한이 (좀) 하위 폴더를 포함하는 전체 소스 폴더를 검색하는 방법을 생각하고 사용하여 특정 단어에 대한 하위 파일 대신 api처럼 하나 개의 단어를 검색

Dir['Source/**/*'].select{|f| File.file?(f) }.each do |filepath| 
    puts filepath 
    puts File.readlines(filepath).any?{ |l| l['api'] } 
end 

, 나는 (즉, 가능한 경우) 단어의 전체 어레이의 소스 폴더를 검색 할.

File.readlines('words.txt').map do |word| 
    array_of_words << word 
end 

메모리에 전체 파일을 읽어, 다음의 개별 요소로 변환 :

+1

루비에서이 작업을 수행해야합니까? 명령 행 도구'egrep'는'egrep -r "(api | function | method)"*'같은 것을 통해 훨씬 쉽게 할 수 있습니다 ... – Brian

+0

안녕하세요 @ 브라이언, 네, 불행히도 루비에 있어야합니다. –

답변

0

재귀 이것을 고려 words.txt

re = /#{File.readlines('words.txt').map { |word| Regexp.quote(word.strip) }.join('|')}/ 

Dir['Source/**/*.{cpp,txt,html}'].select{|f| File.file?(f) }.each do |filepath| 
    puts filepath 
    puts File.readlines(filepath, "r:ascii").grep(re).any? 
end 
+0

words.txt의 내용을 이스케이프 처리하는 답변이 업데이트되었습니다. –

+0

안녕하세요. 정확한 오류가 발생했습니다. '=== ': UTF-8 (ArgumentError)에서 잘못된 바이트 시퀀스 –

+0

'Regexp.quote (word.strip)} .join ('| ')'은 거짓 정보를 생성 할 수 있기 때문에 좋은 생각이 아닙니다. 긍정적 인 하위 문자열 히트. –

2

에 포함 된 단어 중 어떤 디렉토리를 검색 정렬. 다음을 사용하여 동일한 결과를 얻을 수 있습니다.

array_of_words = File.readlines('words.txt') 

잠재적 인 문제는 확장 성이 없다는 것입니다. "words.txt"가 사용 가능한 메모리보다 크면 코드에 문제가 있으므로 조심하십시오.

단어 배열에 대한 파일 검색은 여러 가지 방법으로 수행 할 수 있지만 항상 정규 표현식을 사용하는 것이 가장 쉽습니다. Perl은 단어 목록을 매우 효율적인 패턴으로 쉽게 변환 할 수있는 Regexp :: Assemble이라는 훌륭한 모듈을 가지고 있지만 Ruby는 그러한 종류의 기능이 없습니다. 내가 도움을 줄 수있는 과거의 해결책 중 하나는 "Is there an efficient way to perform hundreds of text substitutions in Ruby?"입니다.

루비에는 Regexp.union이 있지만 부분적인 도움이됩니다.

/#{re}/ # => /(?-mix:foo|bar)/ 

(?-mix: 그렇게하지 않습니다 그래서 당신에게 문제를 일으킬 것입니다 : 다른 패턴으로 보간에주의해야합니다 있도록 패턴을 생성

words = %w(foo bar) 
re = Regexp.union(words) # => /foo|bar/ 

는 표현에 대한 플래그를 가지고있다. 대신 다음과 같이 사용하십시오 :

/#{re.source}/ # => /foo|bar/ 

패턴을 생성하고 예상대로 작동합니다.단어가 다른 단어의 하위 문자열로 볼 수 있기 때문에

불행하게도, 그 어느 완벽한 솔루션이 아니다 :

'foolish'[/#{re.source}/] # => "foo" 

그 패턴 주위에 단어 경계를 설정하는 것입니다 해결하는 방법 : 다음 전체 단어를 찾아

/\b(?:#{re.source})\b/ # => /\b(?:foo|bar)\b/ 

:

'foolish'[/\b(?:#{re.source})\b/] # => nil 

자세한 내용은 Ruby의 Regexp 설명서를 참조하십시오.

일단 패턴을 사용하고 싶다면 검색하는 것이 더 간단한 문제가됩니다. Ruby에는 Find 클래스가있어 디렉토리에서 파일을 재귀 적으로 쉽게 검색 할 수 있습니다. 이 설명서에는 사용 방법이 나와 있습니다.

또는 Dir 클래스를 사용하여 고유 한 방법으로 자갈을 칠할 수 있습니다. 다시 말하지만, 문서에 예제를 사용하고 있지만, 일반적으로 찾기와 함께 사용합니다.

스캔하는 파일을 읽을 때 foreach을 사용하여 줄 단위로 파일을 읽는 것이 좋습니다. File.readFile.readlines이 아니며이 아니므로 Ruby가 큰 파일을 메모리로 읽으려고하면 프로그램이 제대로 작동하지 않을 수 있습니다. 대신 foreach을 사용하면 더 빠르게 실행되는 확장 가능한 코드가 생성됩니다. 자세한 내용은 "Why is "slurping" a file not a good practice?"을 참조하십시오.

위의 링크를 사용하면 효율적으로 실행되고 유연해질 수있는 항목을 빠르게 조합 할 수 있습니다. 이 테스트되지 않은 코드는 시작할 수 있어야


:

WORD_ARRAY = File.readlines('words.txt').map(&:chomp) 
WORD_RE = /\b(?:#{Regexp.union(WORD_ARRAY).source}\b)/ 

Dir['Source/**/*'].select{|f| File.file?(f) }.each do |filepath| 
    puts "#{filepath}: #{!!File.read(filepath)[WORD_RE]}" 
end 

출력됩니다 그것을 읽는 것 파일 및 "true"또는 "false"를에있는 단어 중 하나를 찾는 히트가 있는지 명부.

readlinesread 때문에 확장 가능하지 않으며 파일 중 큰 파일이있는 경우 심각한 속도 저하가 발생할 수 있습니다. 다시 말하지만 위의 "slurp"링크의주의 사항을 참조하십시오.

+0

안녕하세요,이 놀라운/도움이되는 정보를 보내 주셔서 감사합니다. 도와 줘요! –