来自另一个文件的Grep列表(文件)

时间:2019-02-07 08:27:07

标签: bash grep

我是bash的新手,正在尝试从文件中提取模式列表:

File1.txt

ABC
BDF
GHJ

base.csv(尝试用逗号分隔并制表符分隔)

line 1,,,,"hfhf,ferf,ju,ABC"
line 2 ,,,,,"ewy,trggt,gtg,ABC,RFR"
line 3 .."himk,n,hn.ujj., BDF"

建议的输出类似

ABC
line 1..
line 2..(whole lines)
BDF
line 3..

以此类推,针对文件1中的每个模式

我尝试的代码是:

#!/bin/bash
for i in *.txt -# cycle through all files containing pattern lists
do
for q in "$i"; # # cycle through list
do
echo $q >>output.${i}; 
grep -f "${q}" base.csv >>output.${i};
echo "\n";
done
done

但是输出仅是文件名,然后是一些没有模式名称的字符串列表,例如

File1.txt
line 1...
line 2... 
line 3..

所以我不知道每个字符串属于什么模式,必须手动检查和分配。你能指出我的错误吗?谢谢!

4 个答案:

答案 0 :(得分:1)

grep可以一次处理多个文件,然后增加了吸引人的好处,那就是表明它找到了匹配的文件。

grep -f File1.txt base.csv >output.txt

不清楚您希望内部循环做什么;它只会一次循环一个令牌,因此根本不是一个循环。

如果您希望按模式将输出分组,那么这是一个for循环,它一次查找一个模式:

while read -r pat; do
    echo "$pat"
    grep "$pat" *.txt
done <File1.txt >output.txt

但是解决此问题的最有效方法是编写一个简单的Awk脚本,该脚本可立即处理所有输入文件,并在打印匹配项之前对其进行分组。

另一个问题是锚点。 grep "ABC"将在123DEABCXYZ中找到一个匹配项;您要避免这种事情吗?您可以改进正则表达式,或者再次使用Awk,它使您可以更好地控制在结构化行中准确查找匹配项的位置。

awk '# Read patterns into memory
    NR==FNR { a[++i] = $1; next }
    # Loop across patterns
    { for(j=1; j<=i; ++j)
        if($0 ~ a[j]) {
            print FILENAME ":" FNR ":" $0 >>output.a[j]
            next }
    }' File1.txt base.csv

答案 1 :(得分:0)

您实际上并没有在读取文件,只是在处理文件名。试试这个:

#!/bin/bash
for i in *.txt # cycle through all files containing pattern lists
do
  while read -r q # read file line by line
  do
    echo "$q" >>"output.${i}" 
    grep -f "${q}" base.csv >>"output.${i}"
    echo "\n"
  done < "${i}"
done

答案 2 :(得分:0)

这是一个将split到数组(file2)中的单词(用word[]隔开,用引号和空格隔开的逗号分隔)并存储记录名称({ {1}}等),以逗号分隔:

line 1

输出:

awk '
NR==FNR {
    n=split($0,tmp,/[" ]*(,|$)[" ]*/)                                  # split words
    for(i=2;i<=n;i++)                                                  # after first
        if(tmp[i]!="")                                                 # non-empties
            word[tmp[i]]=word[tmp[i]] (word[tmp[i]]==""?"":",") tmp[1] # hash rownames
    record[tmp[1]]=$0                                                  # store records
    next
}
($1 in word) {                                                         # word found
    n=split(word[$1],tmp,",")                                          # get record names
    print $1 ":"                                                       # output word
    for(i=1;i<=n;i++)                                                  # and records
        print record[tmp[i]]
}' file2 file1

答案 3 :(得分:0)

我的朋友,感谢您的帮助。 尝试了以上两种变体,但不断出现各种错误(预期为“执行”)或行为异常(获取模式块的名称,例如ABC,BDF,但没有行。 放弃了一段时间,然后最终尝试了另一种方法 虽然基本目标是循环浏览模式列表文件,但在巨大的文件中搜索模式,并从找到的行中写出特定的列-我只是写了

for *i in *txt  # cycle throughfiles w/ patterns
do
  grep -F -f "$i" bigfile.csv >> ${i}.out1   #greps all patterns from current file
  cut -f 2,3,4,7 ${i}.out1>> ${i}.out2   # cuts columns of interest and writes them out to another file
done

我知道应该使用一些新颖的管道功能来改进此代码,但是它可以正常工作,希望能对类似情况的人有所帮助。您可以轻松添加一些回声以按照我最初的要求写出模式列表名称