2012-03-26 13 views
4

Позвольте мне начать с того, что я не хочу печатать только повторяющиеся строки и не хочу их удалять.Использование grep с файлом шаблона: печать одиночных и повторяющихся записей

Я пытаюсь использовать grep с файлом шаблона для синтаксического анализа большого файла данных.

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

1243 
1234 
1234 
1234 
1354 
1356 
1356 
1677 

и т.д. с более одно- и дублирующихся записей.

файл данных

Входной может выглядеть следующим образом:

aatta 1243 qqqqqq 
yyyyy 1234 vvvvvv 
ttttt 1555 bbbbbb 
ppppp 1354 pppppp 
yyyyy 3333 zzzzzz 
qqqqq 1677 eeeeee 
iiiii 4444 iiiiii 

и т.д. для 27000 линий.

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

grep -f 'Patternfile.txt' 'Inputfile.txt' > 'Outputfile.txt' 

я получаю выходной файл, который напоминает это:

aatta 1243 qqqqqq 
yyyyy 1234 vvvvvv 
ppppp 1354 pppppp 

как бы я могу получить также сообщить дубликаты, так что я в конечном итоге с чем-то вроде этого? :

aatta 1243 qqqqqq 
yyyyy 1234 vvvvvv 
yyyyy 1234 vvvvvv 
yyyyy 1234 vvvvvv 
ppppp 1354 pppppp 


qqqqq 1677 zzzzzz 

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

Спасибо!

ответ

2

Одно из решений, а не с grep, но с perl:

С patternfile.txt и inputfile.txt с данными исходного поста. Следующее содержание script.pl должен делать эту работу (. Я полагаю, что строка соответствует второй столбец, в противном случае он должен быть изменен, чтобы использовать regexp вместо Этот способ быстрее):

use warnings; 
use strict; 

## Check arguments. 
die qq[Usage: perl $0 <pattern-file> <input-file>\n] unless @ARGV == 2; 

## Open input files. 
open my $pattern_fh, qq[<], shift @ARGV or die qq[Cannot open pattern file\n]; 
open my $input_fh, qq[<], shift @ARGV or die qq[Cannot open input file\n]; 

## Hash to save patterns. 
my (%pattern, %input); 

## Read each pattern and save how many times appear in the file. 
while (<$pattern_fh>) { 
    chomp; 
    if (exists $pattern{ $_ }) { 
     $pattern{ $_ }->[1]++; 
    } 
    else { 
     $pattern{ $_ } = [ $., 1 ]; 
    } 
} 

## Read file with data and save them in another hash. 
while (<$input_fh>) { 
    chomp; 
    my @f = split; 
    $input{ $f[1] } = $_; 
} 

## For each pattern, search it in the data file. If it appears, print line those 
## many times saved previously, otherwise print a blank line. 
for my $p (sort { $pattern{ $a }->[0] <=> $pattern{ $b }->[0] } keys %pattern) { 
    if ($input{ $p }) { 
     printf qq[%s\n], $input{ $p } for (1 .. $pattern{ $p }->[1]); 
    } 
    else { 
     # Old behaviour. 
     # printf qq[\n]; 

     # New requirement. 
     printf qq[\n] for (1 .. $pattern{ $p }->[1]); 
    } 
} 

Выполнить это нравится:

perl script.pl patternfile.txt inputfile.txt 

И дает следующий вывод:

aatta 1243 qqqqqq 
yyyyy 1234 vvvvvv 
yyyyy 1234 vvvvvv 
yyyyy 1234 vvvvvv 
ppppp 1354 pppppp 


qqqqq 1677 eeeeee 
+0

Спасибо, это очень близко .. Я также пытаюсь иметь его напечатать пустую строку, если шаблон не найден. Но это была тонна помощи до сих пор! – PlutonicFriend

+0

@PlutonicFriend: Как будет выглядеть пустая строка? Добавьте его в свой вопрос, чтобы получить помощь. Я тоже попробую. – Birei

+0

hmm, забавный стиль с 'qq []' :) – gaussblurinc

1

вы не стольких grep ИНГОВ для моделей, как вы по левому соединению данных в ом ut к данным в шаблоне.

Вы можете (в основном) выполнить это с помощью join, удобной утилиты Unix, которую я очень хорошо знаю, так как я пытался решить проблему, похожую на вашу.

Есть несколько небольших отличий.

Первая команды:

join -a 1 -2 2 <(sort Patternfile.txt) <(sort -k2,3 Inputfile.txt) 

И объяснение:

  • -a 1 означает также включать несоединимую строку из файла 1 (Patternfile.txt). Я добавил это, потому что вы хотели включить «пустые» строки для unmatchable строк, и это было самое близкое, что я мог получить.
  • -2 2 означает присоединиться к полю 2 для файла 2 (Вы можете установить поле для -1 FIELD и -2 FIELD, по умолчанию - поле 1). Это связано с тем, что ключ, с которым вы соединяетесь, находится в . Inputfile.txt находится во втором столбце
  • <(sort Patternfile.txt) — файлы должны быть отсортированы в поле соединения для правильной работы соединения.
  • <(sort -k2,2 Inputfile.txt) — рода входной файл с ключом 2 до ключа 2 включительно

Выход:

1234 yyyyy vvvvvv 
1234 yyyyy vvvvvv 
1234 yyyyy vvvvvv 
1243 aatta qqqqqq 
1354 ppppp pppppp 
1356 
1356 
1677 qqqqq eeeeee 

Различия

Незначительные различия между вашей указанной продукции и этот результат:

  • Сортировка по ключевому заказу.
  • Несвязанные строки по-прежнему содержат исходный ключ. Если это проблема, вы можете очистить несовпадающие строки по конвейеру через простой awk:

    ... | awk '{ if ($2 != "") print; else print "" }'