Как найти пересечение нескольких файлов (не обязательно двух файлов)?

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

Одна из возможностей - запустить поиск в фоновом режиме и записать результат в FIFO. Вы можете читать из FIFO с таймаутом ( читать -t 0.3 ... ).

Думаю, я недавно видел здесь более простое решение, чем FIFO ... но в настоящее время я этого не помню. read -t также работает с конвейером, но завершение read не уничтожает более ранние части конвейера, и конвейер возвращается только после завершения всех его частей.

2
12.12.2018, 08:01
4 ответа

Когда вы разыменовываете RESв:

comm $FILE  ${RES}

содержание RESзаменяет ${RES}. Но commожидает имя файла в качестве аргумента, поэтому, например, если $RESсодержит hellocomm, пытается открыть файл с именем hello.

Вместо этого вы можете использовать временный файл для хранения общих строк во время процесса:

tmp=$(mktemp --tmpdir)
tmp2=$(mktemp --tmpdir)
comm -12 ${1}  ${2} >$tmp

for FILE in ${@:3}
do
    comm -12 $FILE  $tmp >$tmp2
    rm $tmp 
    mv $tmp2 $tmp   
done

cat $tmp 
rm $tmp
1
27.01.2020, 22:02

Проблема в том, что commнужны два файла, а $RESявляется переменной.

Но мы можем обмануть и сделать его похожим на файл, используя подстановку процесса:

#!/bin/bash

RES=$(comm -12 ${1}  ${2})

for FILE in ${@:3}
do
    RES="$(comm -12 $FILE  <(printf %s "${RES}"))"
done

printf %s "$RES"

Вы можете видеть, что это почти то же самое, что и ваш оригинал, но мы используем структуру <(...)для запуска команды и используем ее в качестве имени файла.

Итак, если у нас есть эти три файла:

a:line1
a:line2
a:line3
a:line4
b:line2
b:line4
b:line6
c:line2
c:line4
c:line8

Мы можем сравнить их:

%./allcomp a b c
line2
line4
0
27.01.2020, 22:02

Функция допускает рекурсивный подход

f() {
     if (($# == 1))
     then
         cat $1;
         return;
     fi
     comm -12 $1 <(f "${@:2}")
}

f file1 file2 file3 file4 file5...
2
27.01.2020, 22:02

Ни parallel, ни xargs, ни commне нужны. Попробуйте функцию

$ intersection() {  sort $@ | uniq -c | sed -n "s/^ *$# //p"; }
$ intersection file[1-3]
line2
line4
0
27.01.2020, 22:02

Теги

Похожие вопросы