Как разбить файл, например split на stdout, для подключения к команде?

У меня есть большой файл .sql полный SELECT которые содержат данные, которые я хочу вставить в мою базу данных SQL Server. Я ищу, как я мог в основном взять содержимое файла, по 100 строк за раз, и передать его командам, которые я установил для остальных.

В принципе, я ищу split который будет выводиться на stdout , а не на файлы.

Я также использую CygWin для Windows, поэтому у меня нет доступа к полному набору инструментов.

5 Solutions collect form web for “Как разбить файл, например split на stdout, для подключения к команде?”

Я думаю, что самый простой способ сделать это:

 while IFS= read -r line; do { printf '%s\n' "$line"; head -n 99; } | other_commands done <database_file 

Вы должны использовать read для первой строки в каждом разделе, поскольку, как представляется, нет другого способа остановить, когда достигнут конец файла. Для получения дополнительной информации см .:

  • Проверьте, пуст ли пуст и запустите команду над данными, если это не
  • Как перенести вывод из одного процесса в другой, но только выполнить, если первый имеет выход?
 _linc() ( ${sh-da}sh ${dbg+-vx} 4<&0 <&3 ) 3<<-ARGS 3<<\CMD set -- $( [ $((i=${1%%*[!0-9]*}-1)) -gt 1 ] && { shift && echo "\${inc=$i}" ; } unset cmd ; [ $# -gt 0 ] || cmd='echo incr "#$((i=i+1))" ; cat' printf '%s ' 'me=$$ ;' \ '_cmd() {' '${dbg+set -vx ;}' "$@" "$cmd" ' }' ) ARGS s= ; sed -f - <<-INC /dev/fd/4 | . /dev/stdin i_cmd <<"${s:=${me}SPLIT${me}}" ${inc:+$(printf '$!n\n%.0b' `seq $inc`)} a$s INC CMD размере _linc() ( ${sh-da}sh ${dbg+-vx} 4<&0 <&3 ) 3<<-ARGS 3<<\CMD set -- $( [ $((i=${1%%*[!0-9]*}-1)) -gt 1 ] && { shift && echo "\${inc=$i}" ; } unset cmd ; [ $# -gt 0 ] || cmd='echo incr "#$((i=i+1))" ; cat' printf '%s ' 'me=$$ ;' \ '_cmd() {' '${dbg+set -vx ;}' "$@" "$cmd" ' }' ) ARGS s= ; sed -f - <<-INC /dev/fd/4 | . /dev/stdin i_cmd <<"${s:=${me}SPLIT${me}}" ${inc:+$(printf '$!n\n%.0b' `seq $inc`)} a$s INC CMD 

Вышеприведенная функция использует sed для применения своего списка аргументов в качестве командной строки к произвольному приращению строки. Команды, которые вы укажете в командной строке, отправляются во временную функцию оболочки, которая получает здесь документ на stdin, состоящий из каждого шага стоимости каждого шага.

Вы используете его следующим образом:

 time printf 'this is line #%d\n' `seq 1000` | _linc 193 sed -e \$= -er \- \| tail -n2 #output 193 this is line #193 193 this is line #386 193 this is line #579 193 this is line #772 193 this is line #965 35 this is line #1000 printf 'this is line #%d\n' `seq 1000` 0.00s user 0.00s system 0% cpu 0.004 total 

Механизм здесь очень прост:

 i_cmd <<"${s:=${me}SPLIT${me}}" ${inc:+$(printf '$!n\n%.0b' `seq $inc`)} a$s 

Это сценарий sed . В основном мы просто printf $increment * n; , Поэтому, если вы установили свой приращение на 100 printf вы напишите сценарий sed состоящий из 100 строк, которые говорят только $!n , одну строку insert для верхнего конца здесь-doc и одну append к нижней строке – вот и все. Большинство остальных просто обрабатывает варианты.

Команда n ext сообщает sed распечатать текущую строку, удалить ее и вытащить следующую. $! указывает, что он должен использовать только любую строку, кроме последней.

При условии, что это будет только инкремент:

 printf 'this is line #%d\n' `seq 10` | ⏎ _linc 3 #output incr #1 this is line #1 this is line #2 this is line #3 incr #2 this is line #4 this is line #5 this is line #6 incr #3 this is line #7 this is line #8 this is line #9 incr #4 this is line #10 

Итак, что происходит за кулисами здесь, эта функция настроена на echo счетчик и cat его вход, если не предоставлена ​​командная строка. Если вы видели это в командной строке, это будет выглядеть так:

 { echo "incr #$((i=i+1))" ; cat ; } <<HEREDOC this is line #7 this is line #8 this is line #9 HEREDOC 

Он выполняет одно из них для каждого приращения. Посмотрите:

 printf 'this is line #%d\n' `seq 10` | dbg= _linc 3 #output set -- ${inc=2} + set -- 2 me=$$ ; _cmd() { ${dbg+set -vx ;} echo incr "#$((i=i+1))" ; cat } + me=19396 s= ; sed -f - <<-INC /dev/fd/4 | . /dev/stdin i_cmd <<"${s:=${me}SPLIT${me}}" ${inc:+$(printf '$!n\n%.0b' `seq $inc`)} a$s INC + s= + . /dev/stdin + seq 2 + printf $!n\n%.0b 1 2 + sed -f - /dev/fd/4 _cmd <<"19396SPLIT19396" this is line #1 this is line #2 this is line #3 19396SPLIT19396 + _cmd + set -vx ; echo incr #1 + cat this is line #1 this is line #2 this is line #3 _cmd <<"19396SPLIT19396" размере printf 'this is line #%d\n' `seq 10` | dbg= _linc 3 #output set -- ${inc=2} + set -- 2 me=$$ ; _cmd() { ${dbg+set -vx ;} echo incr "#$((i=i+1))" ; cat } + me=19396 s= ; sed -f - <<-INC /dev/fd/4 | . /dev/stdin i_cmd <<"${s:=${me}SPLIT${me}}" ${inc:+$(printf '$!n\n%.0b' `seq $inc`)} a$s INC + s= + . /dev/stdin + seq 2 + printf $!n\n%.0b 1 2 + sed -f - /dev/fd/4 _cmd <<"19396SPLIT19396" this is line #1 this is line #2 this is line #3 19396SPLIT19396 + _cmd + set -vx ; echo incr #1 + cat this is line #1 this is line #2 this is line #3 _cmd <<"19396SPLIT19396" 

ДЕЙСТВИТЕЛЬНО БЫСТРО

 time yes | sed = | sed -n 'p;n' | _linc 4000 'printf "current line and char count\n" sed "1w /dev/fd/2" | wc -c [ $((i=i+1)) -ge 5000 ] && kill "$me" || echo "$i"' #OUTPUT current line and char count 19992001 36000 4999 current line and char count 19996001 36000 current line and char count [2] 17113 terminated yes | 17114 terminated sed = | 17115 terminated sed -n 'p;n' yes 0.86s user 0.06s system 5% cpu 16.994 total sed = 9.06s user 0.30s system 55% cpu 16.993 total sed -n 'p;n' 7.68s user 0.38s system 47% cpu 16.992 total 

Выше я говорю, чтобы он увеличивался на каждые 4000 строк. 17s позже, и я обработал 20 миллионов строк. Конечно, логика здесь несерьезна – мы только дважды читаем каждую строку и подсчитываем все их персонажи, но возможности довольно открытые. Кроме того, если вы посмотрите внимательно, вы можете заметить, что это, по-видимому, фильтры, обеспечивающие входные данные, которые в большинстве случаев занимают большинство.

Я закончил с чем-то, что кажется грубым, если есть лучший способ, пожалуйста, опубликуйте его:

 #!/bin/sh DONE=false until $DONE; do for i in $(seq 1 $2); do read line || DONE=true; [ -z "$line" ] && continue; lines+=$line$'\n'; done sql=${lines::${#lines}-10} (cat "Header.sql"; echo "$sql";) | sqlcmd #echo "--- PROCESSED ---"; lines=; done < $1 

Запустите с ./insert.sh "File.sql" 100 где 100 – количество строк, обрабатываемых одновременно.

GNU Parallel для этого:

 cat bigfile | parallel --pipe -N100 yourscript 

По умолчанию будет выполняться 1 задание на ядро ​​процессора. Вы можете принудительно запустить одно задание с помощью -j1.

Версия 20140422 включает в себя быструю версию, которая может доставлять 3,5 ГБ / с. Цена заключается в том, что он не может доставить точные 100 строк, но если вы знаете приблизительную длину строки, вы можете установить –block в 100 раз (здесь я предполагаю, что длина строки близка к 500 байтам):

 parallel --pipepart --block 50k yourscript :::: bigfile 

В принципе, я ищу split который будет выводиться на stdout , а не на файлы.

Если у вас есть доступ к --filter gnu split , опция --filter делает именно это:

 '--filter=command' With this option, rather than simply writing to each output file, write through a pipe to the specified shell command for each output file. 

Таким образом, в вашем случае вы можете использовать эти команды с помощью --filter , например

 split -l 100 --filter='{ cat Header.sql; cat; } | sqlcmd; printf %s\\n DONE' infile 

или написать скрипт, например myscript :

 #!/bin/sh { cat Header.sql; cat; } | sqlcmd printf %s\\n '--- PROCESSED ---' 

а затем просто запустить

 split -l 100 --filter=./myscript infile 
  • Где я могу найти скрипт оболочки для команды ls?
  • Почему я получаю ошибки «Идентификация столкновений между ...» и как их исправить?
  • Как я могу распечатать все, кроме последних n символов в bash?
  • Как легко обновить список md5sums?
  • Пользователь Admin не показывает путь к папке в консольной строке, только $
  • проблема с find -exec cp
  • Код ошибки на подсказке
  • Слияние двух файлов после проверки соответствия некоторых столбцов
  • Как выбрать ответ для интерактивной подсказки при установке из сценария оболочки
  • Подводя массив внутри awk?
  • Как сделать вывод для grep неудачным?
  • Linux и Unix - лучшая ОС в мире.