Как найти строки в одном файле, а не в другом, используя bash-скриптинг? - PullRequest
15 голосов
/ 04 августа 2011

Imagine file 1:

#include "first.h"
#include "second.h"
#include "third.h"

// more code here
...

Imagine file 2:

#include "fifth.h"
#include "second.h"
#include "eigth.h"

// more code here
...

Я хочу получить заголовки, которые включены в файл 2, но не в файл 1, тольколиний.Таким образом, при запуске diff из файла 1 и файла 2 выдаст:

#include "fifth.h"
#include "eigth.h"

Я знаю, как это сделать в Perl / Python / Ruby, но я бы хотел сделать это без использования другогоязык программирования.

Ответы [ 5 ]

25 голосов
/ 04 августа 2011

Это однострочный, но не сохраняет порядок:

comm -13 <(grep '#include' file1 | sort) <(grep '#include' file2 | sort)

Если вам нужно сохранить заказ:

awk '
  !/#include/ {next} 
  FILENAME == ARGV[1] {include[$2]=1; next} 
  !($2 in include)
' file1 file2
9 голосов
/ 04 августа 2011

Если можно использовать временный файл, попробуйте следующее:

grep include file1.h > /tmp/x && grep -f /tmp/x -v file2.h | grep include

Этот

  • извлекает все включения из file1.h и записывает их в файл /tmp/x
  • использует этот файл для получения всех строк из file2.h, которые не содержатся в этом списке
  • извлекает все включения из оставшейся части file2.h

Itвероятно, неправильно обрабатывает различия в пробелах и т. д.

РЕДАКТИРОВАТЬ: для предотвращения ложных срабатываний используйте другой шаблон для последнего grep (спасибо jw013 за упоминание этого):

grep include file1.h > /tmp/x && grep -f /tmp/x -v file2.h | grep "^#include"
8 голосов
/ 04 августа 2011

Для этого варианта требуется fgrep с опцией -f.GNU grep (то есть любая система Linux, а затем и некоторая) должна работать нормально.

# Find occurrences of '#include' in file1.h
fgrep '#include' file1.h |
# Remove any identical lines from file2.h
fgrep -vxf - file2.h |
# Result is all lines not present in file1.h.  Out of those, extract #includes
fgrep '#include'

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

6 голосов
/ 09 октября 2014

Если цель не должна быть достигнута только с помощью Bash (то есть использование внешних программ приемлемо), тогда используйте combine из moreutils :

combine file1 not file2 > lines_in_file1_not_in_file2
2 голосов
/ 21 октября 2013

cat $ file1 $ file2 | grep '#include' | сортировать | uniq -u

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