使用参考文件搜索并打印匹配行

时间:2016-08-02 09:44:44

标签: bash shell unix

具有如下所示的文件夹结构./all_files

-rwxrwxrwx  reference_file.txt
drwxrwxrwx  file1.txt
drwxrwxrwx  file2.txt
drwxrwxrwx  file3.txt

reference_file.txt的文件名如下所示

$cat reference_file.txt
file1.txt
file2.txt

file1.txt和file2.txt中的数据如下所示:

$cat file1.txt
step_1
step_2
step_3

现在,我必须从每个文件中采取特定步骤说出st​​ep2

注1:文件名必须出现在reference_file.txt

注2:step2不是第二行:

注3:搜索应该递归执行。

我使用了以下脚本:

#!/bin/sh

for i in cat reference_file.txt;

do
   find . -type f -name $i | grep -v 'FS*' | xargs  grep -F 'step_2'
done<reference_file.txt

使用上面的代码后我没有输出。

# bash -x script.sh
+ for i in cat reference_file.txt
+ find . -type f -name **cat**
+ xargs grep -F 'step_2'
+ for i in cat **reference_file.txt**
+ find . -type f -name reference_file.txt
+ xargs grep -F 'step_2'

添加了新要求:

target = step_XX_2其中XX可以是任何内容,应该跳过搜索..所以希望输出将是.. step_ab_2 step_cd_2 step_ef_2

2 个答案:

答案 0 :(得分:1)

我认为这是你想要实现的目标。请让我知道:

编辑:我以前的版本没有递归搜索。 进一步编辑:请注意,使用find的进程替换意味着此脚本必须在bash而不是sh下运行。

进一步修改规范中的更改:请注意target-E选项更改为grep而不是-F

#!/bin/bash

target='step_.*?_?2'

while read -r name
do
   # EDIT: exclude certain directories
   if [[ $name == "old1" || $name == "old2" ]]
   then
        # do the next iteration of the loop
        continue    
   fi

   while read -r fname
   do
       if [[ $fname != FS* ]]
       then
           # Display the filename (grep -H is not in POSIX)
           if out=$(grep -E "$target" "$fname")
           then
               echo "$fname: $out"
           fi
       fi
   done < <(find . -type f -name "$name")

done < reference_file.txt

请注意,您的跟踪(bash -x)使用了bash,但您的#!行使用了sh。它们是不同的 - 你应该与你正在使用的shell保持一致。

所以,我删除了xargs,它读取字符串标准输入并使用字符串作为参数执行程序。由于我们已经拥有grep的参数字符串,因此我们不需要它。

你的grep -v 'FS*'可能没有达到预期效果。正则表达式FS*表示“F后跟零个或多个S”。与shell模式匹配(globbing)不同。在我的解决方案中,我使用了FS*,因为我使用的是shell,而不是grep

答案 1 :(得分:0)

我认为这个问题与this

重复

您需要的是

#!/bin/sh

for i in `cat reference_file.txt`
    do  find . -type f -name $i | grep -v 'FS*' | xargs  grep -F 'step_2'  
done 

请参阅反引号,并且不要两次读取文件reference_file.txt。