Я читаю строку из файла devices_list.txt.

Vices_list.txt содержит

fridge
dryer
ironbox
microwave 

Файл, который я читаю, - это myappliances.txt. Содержание

I have a fridge
I have another fridge
I have a refridgerator
I have a microwave
I have ironbox at home
I have another microwave
I have a hairdryer

Я использую

grep -o -m1 -f appliances_list.txt myappliances.txt

Выход

fridge

Мой желаемый результат: первое вхождение каждой строки (точное совпадение)

fridge
microwave
ironbox

Может ли кто-нибудь указать мне правильное направление?

1
Nandu 31 Авг 2017 в 19:11

4 ответа

Лучший ответ
$ cat tst.awk
NR==FNR { strings[$0]; ++numStrings; next }
{
    for (i=1;i<=NF;i++) {
        if ($i in strings) {
            print $i
            delete strings[$i]
            if (--numStrings == 0) {
                exit
            }
            break
        }
    }
}

$ awk -f tst.awk appliances_list.txt myappliances.txt
fridge
microwave
ironbox

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

2
Ed Morton 31 Авг 2017 в 18:02

Удалите -m1 и направьте к sort -u:

grep -owf appliances_list.txt myappliances.txt | sort -u

sort -u будет сортировать и затем уникальные строки. Если такая сортировка нежелательна, вам, возможно, придется использовать что-то вроде awk. Perl или Python.

Обратите внимание: чтобы получить только dryer, а не hairdryer, вам нужно grep -w, поэтому в приведенном выше предложении есть -o w .

0
stevesliva 31 Авг 2017 в 16:33

awk :

awk 'NR==FNR{ a[$0]; next }{ 
              gsub(/<\/?[^<>]+>/,"",$0); for(i=1;i<=NF;i++) 
              if ($i in a && !a[$i]){ a[$i]++; print $i; break } 
    }' appliances_list.txt myappliances.txt
  • a[$0]; - захват слов шаблона из appliances_list.txt

  • for(i=1;i<=NF;i++) - итерация по полям / словам строки из myappliances.txt

Выход:

fridge
microwave
ironbox
2
RomanPerekhrest 31 Авг 2017 в 20:31

Измените ваш код следующим образом. Это будет работать очень эффективно (учитывая, что ваш размер файла составляет 2 ГБ)

while read -r appliance; do grep -m1 -ow $appliance myappliances.txt;done<appliances_list.txt

-w: для точного соответствия слова

Выход:

fridge
ironbox
microwave

Объяснение :
Во-первых, в вашем коде -m1 вызывает остановку сопоставления, как только найдено первое совпадение, и останавливает чтение файла, вызывая выход из программы.

То, что вам нужно сделать, это перебрать файл1 и для каждого слова в нем grep над файл2 и использовать вашу логику.

Другое решение:

Используйте head -1 вместе с grep, чтобы прекратить поиск после того, как найдено первое совпадение.

while read -r appliance; do grep -ow $appliance myappliances.txt | head -1; done<appliances_list.txt
1
Rahul Verma 31 Авг 2017 в 19:58