Возможно, это может помочь, если у вас есть более одного случая в строке, а не вложенность:
#cat plop
>a & b & c <ex> a & b & c </ex> a & b & c <ex> a & b & c </ex> a & b & c
#cat plop |sed -e :1 -e 's@\(<ex>[^(</ex>)]*\)&\(.*</ex>\)@\1+\2@;t1'
>a & b & c <ex> a + b + c </ex> a & b & c <ex> a + b + c </ex> a & b & c
Возможно, вы могли бы сделать это немного быстрее, выполнив несколько вызовов find
параллельно.Например, сначала получите все каталоги верхнего уровня и выполните N вызовов поиска, по одному для каждого каталога. Если вы запустите в подоболочке, вы можете собрать вывод и передать его vim или чему-нибудь еще:
shopt -s dotglob ## So the glob also finds hidden dirs
( for dir in $HOME/*/; do
find -L "$dir" -xtype f -name "*.tex" -exec grep -Fli and {} + &
done
) | vim -R -
Или, чтобы убедиться, что вы начнете получать вывод только после того, как все находки будут завершены:
( for dir in $HOME/*/; do
find -L "$dir" -xtype f -name "*.tex" -exec grep -Fli and {} + &
done; wait
) | vim -R -
Я провел несколько тестов и скорость для вышеупомянутого действительно была немного выше, чем у единственной находки
. В среднем, более 10 запусков, одно средство вызова find
- 0,898 секунды, а приведенная выше подоболочка - запуск одного поиска для каждого каталога - 0,628 секунды.
Я предполагаю, что детали всегда будут зависеть от того, сколько каталогов у вас есть в $ HOME
, сколько из них может содержать файлы .tex
и сколько может совпадать, так что ваш пробег может различаться.
Поскольку вы используете ack
и Silver Searcher ( ag
), кажется, что вы можете использовать дополнительные инструменты.
Новый инструмент в этой области - ripgrep ( rg
). Он разработан, чтобы быть быстрым как при поиске файлов для поиска (например, ag
), так и при поиске самих файлов (как старый добрый GNU grep
).
В качестве примера в вашем вопросе вы можете использовать его примерно так:
rg --files-with-matches --glob "*.tex" "and" "$HOME"
Автор ripgrep опубликовал подробный анализ того, как работают различные инструменты поиска, а также сравнительные тесты.
Один из тестов, linux-literal-casei
, в некоторой степени похож на задачу, которую вы описываете. Он выполняет поиск по большому количеству файлов во множестве вложенных каталогов (кодовая база Linux), ища строковый литерал без учета регистра.
В этом тесте rg
был самым быстрым при использовании белого списка (например, в вашем примере с «* .tex»). Инструмент ucg
также хорошо показал себя в этом тесте.
rg (игнорировать) 0,345 +/- 0,073 (строки: 370) rg (игнорировать) (mmap) 1,612 +/- 0,011 (строки: 370) ag (игнорировать) (mmap ) 1,609 +/- 0,015 (строки: 370) pt (игнорировать) 17,204 +/- 0,126 (строки: 370) просеять (игнорировать) 0,805 +/- 0,005 (строки: 370) { {1}} git grep (игнорировать) 0,343 +/- 0,007 (строки: 370) rg (белый список) 0,222 +/- 0,021 (строки: 370) + ucg (белый список) 0,217 + / - 0,006 (строк: 370) *
* - Лучшее среднее время. + - Лучшее время выборки.
Автор исключил ack
из тестов, потому что он был намного медленнее других.