Grep список (файл) из другого файла - PullRequest
0 голосов
/ 07 февраля 2019

Я новичок в 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 голосов
/ 22 февраля 2019

Спасибо за вашу помощь, друзья мои.Пробовал оба варианта выше, но продолжал получать различные ошибки (ожидаемое "do") или неправильное поведение (получает имена блоков паттернов, например, 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

Я знаю, что этот код должен быть улучшен с использованием некоторых необычных функций конвейера, но этоработает отлично, как есть, надеюсь, это поможет кому-то в подобной ситуации. Вы можете легко добавить несколько эхо-сигналов для записи имен списков шаблонов, как я изначально просил

0 голосов
/ 07 февраля 2019

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
0 голосов
/ 07 февраля 2019

Вот тот, который разделяет (с split, запятая с разделителями кавычек и пробелов) слова из file2 в массив (word[]) и сохраняет имена записей (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

Вывод:

ABC:
line 1,,,,"hfhf,ferf,ju,ABC"
line 2 ,,,,,"ewy,trggt,gtg,ABC,RFR"
BDF:
line 3 .."himk,n,hn.ujj., BDF"
0 голосов
/ 07 февраля 2019

Вы на самом деле не читаете файлы, вы просто обрабатываете имена файлов.Попробуйте это:

#!/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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...