_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
Die obige Funktion verwendet sed
, um ihre Argumentliste als Befehlszeichenfolge auf ein beliebiges Zeileninkrement anzuwenden. Die Befehle, die Sie in der Befehlszeile angeben, werden in eine temporäre Shell-Funktion eingespeist, die ein Here-Dokument auf stdin erhält, das aus den Zeilenzeilen aller Inkremente besteht.
Sie verwenden es so:
time printf 'this is line #%d\n' `seq 1000` |
_linc 193 sed -e \$= -e r \- \| 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
Der Mechanismus hier ist sehr einfach:
i_cmd <<"${s:=${me}SPLIT${me}}"
${inc:+$(printf '$!n\n%.0b' `seq $inc`)}
a$s
Das ist das sed
Drehbuch. Grundsätzlich haben wir nur printf $increment * n;
. Wenn Sie also Ihr Inkrement auf 100 setzen printf
, erhalten Sie ein sed
Skript, das aus 100 Zeilen besteht, die nur sagen $!n
, eine insert
Zeile für das obere Ende des Here-Dokuments und eineappend
für die untere Zeile - fertig. Der größte Teil des Restes behandelt nur Optionen.
Der n
Befehl ext weist Sie sed
an, die aktuelle Zeile zu drucken, zu löschen und die nächste zu ziehen. Das $!
gibt an, dass es nur eine Zeile außer der letzten versuchen soll.
Vorausgesetzt, nur ein Inkrementierer wird es:
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
Was hier also hinter den Kulissen passiert, ist, dass die Funktion auf echo
einen Zähler gesetzt und cat
dessen Eingabe erfolgt, wenn keine Befehlszeichenfolge angegeben wird. Wenn Sie es in der Befehlszeile sehen würden, würde es so aussehen:
{ echo "incr #$((i=i+1))" ; cat ; } <<HEREDOC
this is line #7
this is line #8
this is line #9
HEREDOC
Es führt eine davon für jedes Inkrement aus. Aussehen:
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"
WIRKLICH SCHNELL
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
Oben sage ich, dass es alle 4000 Zeilen erhöht werden soll. 17s später habe ich 20 Millionen Zeilen verarbeitet. Natürlich ist die Logik dort nicht ernst - wir lesen jede Zeile nur zweimal und zählen alle ihre Zeichen, aber die Möglichkeiten sind ziemlich offen. Auch wenn Sie genau hinschauen, werden Sie vielleicht bemerken, dass es anscheinend die Filter sind, die die Eingabe liefern, die sowieso die meiste Zeit in Anspruch nehmen.
BULK INSERT
? Trennen Sie die Daten von der SQL-Anweisung.