Удаление строк из файла с двоичными строками - PullRequest
0 голосов
/ 30 мая 2018

У меня есть два файла.Файл A содержит текст, записанный в N строках, а файл B содержит строку двоичного шаблона 0 и 1, которая также имеет длину N.

Я хочу удалить строки из файла A, который имеет тот же номер строки, что ив файле B, который содержит 0.

Я читал, что было бы неплохо сделать это с помощью awk, но я понятия не имею, как его использовать.

Файлы очень длинные, например, 2000 строк (это видео-следы)

Например:

Файл A:

Line 1: 123456
Line 2: 789012
Line 3: 345678
Line 4: 901234

Файл B:

Line 1: 1
Line 2: 0
Line 3: 0
Line 4: 1

После исполнения:

Файл A:

Line 1: 123456
Line 2: 901234

Ответы [ 8 ]

0 голосов
/ 31 мая 2018

paste и sed комбинированный:

paste -d'\n' fileB fileA | sed -n '/^1$/{n;p}'
123456
901234

Вы чередуете файлы:

1
123456
0
789012
0
345678
1
901234

Затем вы используете sed для печати строк, следующих непосредственно за линиейкоторый имеет только 1.Однако это не будет работать должным образом, если у вас есть записи, которые состоят только из 1 в fileA.Если это так, то вы должны использовать следующую команду sed, которая учитывает, обрабатываем ли мы в настоящее время нечетную / четную строку:

paste -d'\n' fileB fileA | sed -n '1~2{/^1$/{n;p}}'
0 голосов
/ 30 мая 2018

Предположим, Line 1: и т. Д. На самом деле не существует во ваших входных файлах, все что вам нужно:

awk 'NR==FNR{a[NR]=$0;next} a[FNR]' fileB fileA
0 голосов
/ 30 мая 2018

другое paste / awk решение.Если в данных появляется вкладка, найдите другой разделитель.

paste file2 file1 | awk -F'\t' '$1{print $2}' 
0 голосов
/ 30 мая 2018

Здесь много интересных ответов.Вот один из них:

while IFS= read -r -u3 line; IFS= read -r -u4 bool; do 
    ((bool == 1)) && printf "%s\n" "$line"
done 3<fileA 4<fileB

Это будет намного медленнее, чем другие решения.

0 голосов
/ 30 мая 2018

РЕДАКТИРОВАТЬ: @ комментарий codeforester, если Line 1 или Line 2 не являются частью вашего File1 и File2, то может помочь следующее.

awk 'FNR==NR{a[FNR]=$0;next} $0!=0{print a[FNR]}' filea fileb

Решение 2-е: Сначала чтение файла fileb, а затем чтение filea.

awk 'FNR==NR{if($0!=0){a[FNR]=$0};next} a[FNR]' fileb filea


Вариант решения 1st в случае, если в OP есть строка (s)) line1, line2 в его / ее файлах.

После awk может помочь и здесь.

awk '
FNR==NR{
  a[FNR]=$NF;
  next}
$NF!=0{
  printf("%s%s\n","Line " ++count": ",a[FNR])
}' filea fileb
0 голосов
/ 30 мая 2018

Отдельная команда awk может читать из обоих файлов.

awk '(getline flag < "fileB") > 0 && flag' fileA

После чтения каждой строки из fileA, прочитать строку из fileB в флаг переменной и проверить, является ли ее целочисленное значениеэто правда или нет.Для истинных значений выводится строка из fileA.

В зависимости от вашей версии awk, вам может потребоваться использовать int(flag) или flag+0, чтобы заставить значение рассматриваться как целое числоа не обычная непустая строка.

0 голосов
/ 30 мая 2018

Для этого можно использовать paste и cut:

paste fileB fileA | grep '^1' | cut -f2-
  • paste fileB fileA - вставляет содержимое файла рядом друг с другом, разделяя вкладкой
  • grep '^1' - фильтрует строки, начинающиеся с 1
  • cut -f2- - извлекает необходимое нам содержимое

И cut, и paste используют табуляцию в качестве разделителя по умолчанию.

Это очень похоже на решение Бенджамина .Небольшое преимущество заключается в том, что он будет работать, даже если в fileA будет более одного поля на строку.

0 голосов
/ 30 мая 2018

Вы можете использовать decorate - filter - undecorate pattern:

paste fileA fileB | grep -v '0$' | cut -f1

Это печатает строки каждого файла рядом друг с другом (paste), затем фильтрует строкизаканчивающийся на 0 (grep), затем удаляет строки из второго файла (cut).

Это прерывание, если fileA содержит разделитель, используемый для paste и cut(вкладка по умолчанию).Чтобы избежать этого, мы могли бы либо поменять местами файлы (см. ответ codeforester ), либо прибегнуть к чему-то вроде

paste fileA fileB | sed -n '/1$/s/\t.$//p'

(если строка заканчивается 1, удалить символ табуляции и последний символ,затем напечатайте) или

paste fileA fileB | grep -Po '.*(?=\t1$)'

(сопоставлять только строки, заканчивающиеся на 1, используйте упреждающий просмотр нулевой ширины, чтобы исключить табуляцию и 1 из соответствия);последнее решение требует grep, который поддерживает Perl-совместимые регулярные выражения (PCRE), такие как GNU grep.

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