2017-03-24 194 views
1

我在Crystal中编写了一个工具,它接受一些命令行参数,并将其转换为基本上“find stuff | xargs grep”,其中xargs被指示使用多个进程。这是通过Process.run运行的,并且输出和错误被重定向到一个自定义的IO对象中,该对象过滤了grep中的一些内容,将没有被过滤的内容写入STDOUT。将shell命令的输出输出为grep导致“grep:write error”

当我正常运行它,它似乎运行良好。虽然在搜索完成之前似乎有一些输出实例被切断,所以我不确定我能完全信任结果。然而,当我将这个命令的输出输出到grep时,它总是会提前切断搜索并说“grep:write error”。我不知道为什么会发生这种情况,并希望得到一些帮助。最终,我可能会重写这一切,以完成纯粹Crystal的所有工作,但现在这是一个快速解决方案,用于搜索我正在处理的代码库。

这里是让运行代码:

class FindFilterIO 
include IO 

@@generic_filter = [".diff", ".iml", "/target/"] 
@@web_filter = [".css", ".js", ".jsp", ".ftl"] 

def initialize(@web_search : Bool = false) 
end 

def read(slice : Bytes) 
    raise "FindFilterIO does not support reading!" 
end 

def write(slice : Bytes) 
    str = String.new slice 
    if @@generic_filter.any? { |e| str.includes? e } 
    return 
    end 

    if @web_search 
    if [email protected]@web_filter.any? { |e| str.includes? e } 
     return 
    end 
    end 

    STDOUT.write(slice) 
end 
end 

    cmd = "find . -not \\(-path ./.svn -prune \\) " \ 
     "-not \\(-path ./.idea -prune \\) " \ 
     "-type f -print0 " \ 
     "| xargs -0 -P 1 -n 100 grep -E -n --color=always " 
    cmd += if @html_id 
      "'id=['\"'\"'\"]#{@search_text}['\"'\"'\"]|\##{@search_text}'" 
     elsif @html_class 
      "'class=['\"'\"'\"]#{@search_text}['\"'\"'\"]|\\.#{@search_text}'" 
     else 
      "'#{@search_text}'" 
     end 
    io = FindFilterIO.new web_search: (@html_id || @html_class) 
    Process.run(cmd, output: io, error: io, shell: true, chdir: File.join(@env.home_dir, @env.branch, "repodir")) 
+2

这是一个众所周知的bug:https://github.com/crystal-lang/crystal/issues/2065 – asterite

回答