Почему fgrep ведет себя странно? - PullRequest
2 голосов
/ 29 мая 2020

Я пытаюсь использовать grep для извлечения совпадающих слов из file1 в file2 и направления в выходной файл.

У меня есть file1

Acetoanaerobium sticklandii
Acetobacter pasteurianus

как> 1000 видов.

File2

>WP_013360383.1 ATP-dependent Clp protease ATP-binding subunit [Acetoanaerobium sticklandii]
>WP_013360396.1 ATP-dependent Clp protease ATP-binding subunit [Acetoanaerobium sticklandii]
>WP_003623694.1 multidrug efflux RND transporter permease subunit [Acetobacter pasteurianus]
>WP_003624003.1 superoxide dismutase [Acetobacter pasteurianus]
>WP_003624029.1 UDP-galactopyranose mutase [Acetobacter pasteurianus]
>WP_003624540.1 mannose-1-phosphate guanylyltransferase/mannose-6-phosphate isomerase [Acetobacter pasteurianus]
>WP_077905956.1 effector protein [Salmonella enterica]
>WP_077905962.1 type III secretion system YopJ family effector AvrA [Salmonella enterica]
>WP_005544680.1 3-deoxy-8-phosphooctulonate synthase [Aggregatibacter actinomycetemcomitans]
>WP_005545812.1 MFS transporter [Aggregatibacter actinomycetemcomitans]
>WP_005546163.1 UTP--glucose-1-phosphate uridylyltransferase GalU [Aggregatibacter actinomycetemcomitans]

и так далее ..

когда я использую код

grep -f file1 file2 > output 

или

fgrep -f file1 file2 > output

результирующий вывод - это список, содержащий последнюю строку файла file1, а оставшийся список ввода игнорируется grep. Даже с параметром -w вывод такой же.

Почему grep ведет себя так? Это проблема с моей оболочкой? Я использую MacBook с версией ОС Mojave.

Пожалуйста, предложите мне эквивалентные команды awk.

Я пробовал

awk 'NR==FNR{a[$0];next}$NF in a{print}' file1 file2 > output

, но в результате оказался пустой файл.

Ответы [ 2 ]

3 голосов
/ 29 мая 2020

1-е решение: Generi c и более быстрое решение, чем мое второе решение здесь. Это будет искать строку от [ до ] в Input_file2 независимо от жесткой кодировки поля здесь.

awk '
{ gsub(/\r/,"") }
FNR==NR{
  array[$0]
  next
}
match($0,/\[[^]]*/){
  val=substr($0,RSTART+1,RLENGTH-1)
}
(val in array)
' file1 file2

Пояснение: Добавлено подробное объяснение для выше.

awk '                                     ##Starting awk program from here.
{ gsub(/\r/,"") }
FNR==NR{                                  ##Checkiing condition FNR==NR which will be TRUE hen file1 is being read.
  array[$0]                               ##Creating array with index of current line.
  next                                    ##next will skip all statements from here.
}
match($0,/\[[^]]*/){                      ##Using match to match from [ to till ] in line.
  val=substr($0,RSTART+1,RLENGTH-1)       ##Creating val which has sub-string from RSTART  to RLENGH here.
}
(val in array)                            ##Checking condition if val is present in array then print that line.
' file1 file2                             ##Mentioning Input_file names here.


2-е решение: Не могли бы вы попробовать следующие, написанные и протестированные с показанными образцами. Это более общее c решение, поскольку номер поля НЕ жестко закодирован в решении, но этот код будет работать независимо от номеров полей здесь.

awk '{ gsub(/\r/,"") } FNR==NR{array[$0];next} {for(i in array){if(match($0,i)){print;next}}}' file1 file2

Пояснение: Добавление подробного объяснения вышеизложенного.

awk '                    ##Starting awk program from here.
{ gsub(/\r/,"") }
FNR==NR{                 ##Checking condition FNR==NR if that's true then do following.
  array[$0]              ##Creating an array with index of current line.
  next                   ##next will skip further statements from here.
}
{
  for(i in array){       ##Looping through array here.
    if(match($0,i)){     ##Checking if current key is present  in current line then do following.
      print              ##Printing current line here.
      next               ##next will skip further statements from here.
    }
  }
}
'  file1 file2           ##Mentioning Input_file names here.
2 голосов
/ 29 мая 2020

Проблема с вашим условием соответствия $NF in a означает соответствие sticklandii] полному содержимому строки в первом файле.

Лучшим подходом было бы установить разделитель для обработки всей строки внутри [..] во втором файле против первого файла

*
awk 'NR == FNR{ a[$0]; next } $2 in a' f1 FS='[][]' f2

FS='[][]' перед вторым файлом, чтобы установить поле разделитель на [], что означает, что вы можете получить доступ к записям в [..] по номерам столбцов, которые в вашем случае равны $2.


Что касается вашей исходной проблемы fgrep не работает, вы необходимо добавить флаг -F, чтобы сделать строки из второго файла «фиксированными» строками, а не строками регулярного выражения. Так что вы можете сделать

fgrep -Ff file1 file2
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...