Bash 在1000个文件中搜索字符串,每个文件大小为1GB

Bash 在1000个文件中搜索字符串,每个文件大小为1GB,bash,shell,unix,hadoop,grep,Bash,Shell,Unix,Hadoop,Grep,我正在研究SunOS(它有点脑死亡)。下面是上述Solaris机器的磁盘吞吐量- bash-3.00$ iostat -d 1 10 sd0 sd1 sd2 sd3 kps tps serv kps tps serv kps tps serv kps tps serv 0 0 0 551 16 8 553 16 8 554 16 8 0 0 0 701 11

我正在研究SunOS(它有点脑死亡)。下面是上述Solaris机器的磁盘吞吐量-

bash-3.00$ iostat -d 1 10
    sd0           sd1           sd2           sd3
kps tps serv  kps tps serv  kps tps serv  kps tps serv
  0   0    0  551  16    8  553  16    8  554  16    8
  0   0    0  701  11   25    0   0    0  1148  17   33
  0   0    0    0   0    0    0   0    0    0   0    0
  0   0    0    0   0    0    0   0    0    0   0    0
  0   0    0    0   0    0    0   0    0    0   0    0
  0   0    0    0   0    0    0   0    0    0   0    0
  0   0    0    0   0    0    0   0    0    0   0    0
  0   0    0    0   0    0    0   0    0    0   0    0
  0   0    0    0   0    0    0   0    0    0   0    0
  0   0    0    0   0    0    0   0    0    0   0    0
问题陈述

我大约有
1000个文件
,每个文件的大小为
1GB
。我需要在所有这些
1000个文件中找到
String
,以及哪些文件包含该字符串。我正在使用
Hadoop文件系统
,所有那些
1000个文件
都在Hadoop文件系统中

所有
1000个文件
都在
real-time
文件夹下,因此如果我这样做,我将获得所有
1000个文件
。我需要找到哪些文件包含特定的字符串

bash-3.00$ hadoop fs -ls /apps/technology/b_dps/real-time
对于上面的问题陈述,我使用下面的命令来查找包含特定字符串的所有文件-

hadoop fs -ls /apps/technology/b_dps/real-time | awk '{print $8}' | while read f; do hadoop fs -cat $f | grep cec7051a1380a47a4497a107fecb84c1 >/dev/null && echo $f; done
因此,在上述情况下,它将找到包含此字符串的所有文件cec7051a1380a47a4497a107fecb84c1。它对我来说工作得很好,我能够得到包含特定字符串的文件名

我的问题是-

但上述命令的问题是,它的速度非常慢。那么,我们有没有办法将上面的命令并行化,或者让上面的命令更快地搜索文件


如果您有任何建议,我们将不胜感激。

如果您愿意,可以编写一个简单的MapReduce作业来实现这一点。实际上,您不需要任何减速器,因此减速器的数量将设置为零。通过这种方式,您可以利用MapReduce和chunk的并行处理能力,尽管文件的处理速度比串行grep快得多

只需设置一个可以配置为搜索所需字符串的映射器。您可能会使用TextInputFormat读入文件,拆分行并检查正在搜索的值。然后,您可以为匹配的映射器写出当前输入文件的名称

更新:


要继续此操作,可以从标准字数示例开始:。您可以删除减速器,只需修改映射器即可。当该行作为文本对象包含在值中时,它读取输入行。我不知道您的数据是什么格式,但您甚至可以将文本转换为字符串,并根据该值硬编码a.contains(“”),以查找您正在搜索的字符串(为了简单,而不是速度或最佳实践)。你只需要确定当你点击时映射程序正在处理哪个文件,然后写出文件名。

你可以从grep类得到提示。它与示例文件夹中的分发版一起提供

./bin/hadoop-jar hadoop-mapred-examples-0.22.0.jar grep输入输出正则表达式

有关此类实现的详细信息,请转到目录。发行版附带的“src\examples\org\apache\hadoop\examples”

所以你可以在你的主课上这样做:
您可以在SearchMapper.class中执行此操作。

   public void map(K key, Text value,
                      OutputCollector<Text, LongWritable> output,
                      Reporter reporter)
        throws IOException {
        String text = value.toString();
        Matcher matcher = pattern.matcher(text);
        if(matcher.find()) {
          output.collect(key,value);
}
public void映射(K键,文本值,
输出采集器输出,
(记者)
抛出IOException{
字符串文本=value.toString();
Matcher Matcher=pattern.Matcher(文本);
if(matcher.find()){
输出。收集(键、值);
}

如果您有1000个文件,是否有理由使用细粒度的并行化技术?为什么不使用xargs或gnu parallel,并在文件上拆分工作,而不是在文件中拆分工作

此外,它看起来像是在对一个文本字符串(而不是正则表达式)进行grep;您可以使用-F grep标志来搜索字符串文本,这可能会加快搜索速度,具体取决于grep的实现/优化方式


我没有专门与mapReduce合作过,所以这篇文章可能有点意思,也可能没有点意思。

谢谢Binary的评论,我写mapReduce作业不是很好。你能在这里帮助我们吗?如果你需要的话,我可以提供更多关于文件结构的细节。通过这篇文章,我将能够了解更多。我添加了一些建议,希望能帮助你我会帮你的。如果文件很大,而且命中率在文件的早期,
grep-l模式文件
而不是
grep模式文件>/dev/null&&echo文件
将提供实质性的优化。
grep-q
将提供类似的好处。所以你是说,我应该这样做
grep-l cec7051a1380a47a4497a107fecb84c1>/dev/null
?如果您有输入文件名,
grep-l模式文件
将打印文件名,并在找到匹配项后立即退出。如果输入来自管道,
grep-q模式和打印文件名
。无需重定向到
/dev/null
。这是假定您有
grep
当然,这些选项标志。如果必须在Unix中执行,那么当您提到有关使用
-F grep
时,我需要在上面的命令中做哪些更改。您可以修改我的Unix命令以便我能更了解它吗?这将帮助我理解它。grep-F cec7051a1380a47a4497a107fecb84c
grep-F cec7051a380a47a4497a107fecb84c*
fgrep cec7051a1380a47a4497a107fecb84c*
您需要结尾的类型-在这种情况下,通配符“*”表示在所有文件中搜索。您能解释一下OutputCollector与上下文相比是什么吗?我看到一些映射程序使用上下文,而不是这个OutputCollector,所以我认为您需要添加searchpattern-示例:
Pattern p=Pattern.compile(“”;
Matcher-Matcher=p.Matcher(text);
   public void map(K key, Text value,
                      OutputCollector<Text, LongWritable> output,
                      Reporter reporter)
        throws IOException {
        String text = value.toString();
        Matcher matcher = pattern.matcher(text);
        if(matcher.find()) {
          output.collect(key,value);
}