У вас могут быть похожие проблемы без завершения табуляции. Это не приводит к технической разнице, т. Е. Применяются те же решения.
Одна из возможностей - запустить поиск в фоновом режиме и записать результат в FIFO. Вы можете читать из FIFO с таймаутом ( читать -t 0.3 ...
).
Думаю, я недавно видел здесь более простое решение, чем FIFO ... но в настоящее время я этого не помню. read -t
также работает с конвейером, но завершение read
не уничтожает более ранние части конвейера, и конвейер возвращается только после завершения всех его частей.
Когда вы разыменовываете RES
в:
comm $FILE ${RES}
содержание RES
заменяет ${RES}
. Но comm
ожидает имя файла в качестве аргумента, поэтому, например, если $RES
содержит hello
comm
, пытается открыть файл с именем 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
Проблема в том, что 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
Функция допускает рекурсивный подход
f() {
if (($# == 1))
then
cat $1;
return;
fi
comm -12 $1 <(f "${@:2}")
}
f file1 file2 file3 file4 file5...
Ни parallel
, ни xargs
, ни comm
не нужны. Попробуйте функцию
$ intersection() { sort $@ | uniq -c | sed -n "s/^ *$# //p"; }
$ intersection file[1-3]
line2
line4