У меня есть два текстовых файла: string.txt и lengths.txt
String.txt:
abcdefghijklmnopqrstuvwxyz
lengths.txt
5
4
10
7
Я хочу получить файл
>Entry_1
abcde
>Entry_2
fghi
>Entry_3
jklmnopqrs
>Entry_4
tuvwxyz
Я работаю с около 28 000 записей, и они варьируются от 200 до 56 000 символов.
На данный момент я использую:
start=1
end=0
i=0
while read read_l
do
let i=i+1
let end=end+read_l
echo -e ">Entry_$i" >>outfile.txt
echo "$(cut -c$start-$end String.txt)" >>outfile.txt
let start=start+read_l
echo $i
done <lengths.txt
Но это очень неэффективно. Есть идеи получше?
linux
shell-script
user3891532
источник
источник
str="$(cat string.txt)"; i=0; while read j; do echo "${file:$i:$j}"; i=$((i+j)); done <length.txt
кажется достаточно быстрым, как это делает только снаряд ..{ while read l<&3; do head -c"$l"; echo; done 3<lengths.txt; } <String.txt
.Ответы:
Ты можешь сделать
Это требует некоторого объяснения:
Основная идея заключается в использовании
{ head ; } <file
и получена из недооцененного ответа @mikeserv . Однако в этом случае нам нужно использовать многоhead
s, поэтомуwhile
введен цикл и немного доработаны с файловыми дескрипторами, чтобы перейти кhead
входным данным из обоих файлов (файлString.txt
в качестве основного файла для обработки и строки изlength.txt
в качестве аргумента для-c
опции) , Идея заключается в том, что выигрыш в скорости должен заключаться в том, что вам не нужно искатьString.txt
каждый раз, когда командаhead
или командаcut
вызывается.echo
Просто напечатать строку после каждой итерации.Насколько это быстрее (если есть) и сложение
>Entry_i
между строками оставлено в качестве упражнения.источник
read -u 3
для чтения из дескриптора 3.bash
. Подавляющее большинство систем на основе Linux неbash
установлено (например, Android и другие встроенные системы).bash
будучи самой медленной оболочкой всего, переход на баш, скорее всего , к снижению производительности более существенно , чем небольшой прирост , что переход отread <&3
кread -u3
могут принести (который в любом случае будет незначительным по сравнению со стоимостью запуска внешней команды , какhead
). Переключение на ksh93 соhead
встроенной (и поддерживающей нестандартную-c
опцию) значительно улучшило бы производительность.head -c
(дляhead
реализаций, где доступна эта нестандартная опция) является количество байтов, а не символов. Это будет иметь значение в многобайтовых локалях.Как правило, вы не хотите использовать циклы оболочки для обработки текста . Здесь я бы использовал
perl
:Это одна команда, которая читает (с буферизацией намного более эффективно, чем команда оболочки,
read
которая читает один байт (или несколько байтов для обычных файлов) за раз) оба файла только один раз (без сохранения их в памяти), поэтому будет на несколько порядков эффективнее решений, которые запускают внешние команды в цикле оболочки.(добавьте
-C
опцию, если эти числа должны быть числами символов в текущей локали, а не количеством байтов. Для символов ASCII, как в вашем примере, это не будет иметь никакого значения).источник
$_
как выходного, так и входного параметраread
, но это уменьшает количество байтов в скрипте.bash
, 16 секунд сPATH=/opt/ast/bin:$PATH ksh93
)).Баш, версия 4
выход
источник
Как насчет
awk
?Создайте файл
process.awk
с таким кодом:Сохраните его и выполните
awk -f process.awk lengths.txt string.txt
источник
PROCINFO
, это не стандартноawk
, ноgawk
. В этом случае я бы предпочел еще однуgawk
особенностьFIELDWIDTHS
:awk -vFIELDWIDTHS="$(tr '\n' ' ' < lengths.txt)" '{for(i=1;i<=NF;i++)print">Entry"i ORS$i}' string.txt