2017-05-23 6 views
-1

Ich habe eine Datei, die ich in eine Datenbanktabelle importieren möchte, aber ich möchte ein Stück in jeder Zeile haben. In dem Import, ich brauche für jede Zeile des Versatz (erste Byte) und die Länge (Anzahl von Bytes)Leistung: While-Schleife mit AWK

I habe die folgenden Dateien, um anzuzeigen:

*line_numbers.txt* -> Each row contains the number of 
         the last row of a record in *plans.txt*. 

*plans.txt* -> All the information required for all the rows. 

Ich habe den folgenden Code:

"plans.txt.0.504/" 
"plans.txt.505.480/" 
"plans.txt.984.480/" 
"plans.txt.1464.1159/" 
"plans.txt.2623.515/" 
:
#Starting line number of the record 
sLine=0 

#Starting byte value of the record 
offSet=0 

while read line 
do 
    endByte=`awk -v fline=${sLine} -v lline=${line} \ 
       '{if (NR > fline && NR < lline) \ 
         sum += length($0); } \ 
       END {print sum}' plans.txt` 
    echo "\"plans.txt.${offSet}.${endByte}/\"" >> lobs.in 
    sLine=$((line+1)) 
    offSet=$((endByte+offSet)) 
done < line_numbers.txt 

Dieser Code wird in der lobs.in etwas ähnliche Datei schreiben

Das bedeutet beispielsweise, dass der erste Satz am Byte beginnt und für die nächsten Bytes fortfährt. Der nächste beginnt am Byte und fährt für die nächsten Bytes fort.

Ich muss noch mehr Tests ausführen, aber es scheint zu funktionieren. Mein Problem ist, es ist sehr sehr langsam für das Volumen, das ich verarbeiten muss.

Haben Sie irgendwelche Leistungstipps?

Ich sah in einer Weise, die Schleife in awk einfügen, aber ich brauche 2 Eingabedateien und ich weiß nicht, wie es ohne die Weile zu verarbeiten.

Vielen Dank!

+0

See [warum-ist-mit-a-Shell-Loop-to-Process-Text-als-bad-Praxis] (https://unix.stackexchange.com/questions/169716/why -ist-mit-a-shell-loop-to-process-text-betrachtet-bad-practice) aus einigen Gründen, um Text nicht mit einer Shell-Schleife zu manipulieren. Verwenden Sie einfach awk. Bearbeiten Sie Ihre Frage, um eine übersichtliche, testbare Beispieleingabe und erwartete Ausgabe zu erhalten, damit wir Ihnen helfen können. –

Antwort

0

Doing dies alles in awk wäre viel schneller.

Angenommen, Sie haben:

$ cat lines.txt 
100 
200 
300 
360 
10000 
50000 

Und:

$ awk -v maxl=50000 'BEGIN{for (i=1;i<=maxl;i++) printf "Line %d\n", i}' >data.txt 

(Sie haben also Line 1\nLine 2\n...Line maxl in der Datei data.txt)

Sie etwas tun würde, wie:

awk 'FNR==NR{lines[FNR]=$1; next} 
      {data[FNR]=length($0); next} 
    END{ sl=1 
      for (i=1; i in lines; i++) { 
       bc=0 
       for (j=sl; j<=lines[i]; j++){ 
        bc+=data[j] 
       } 
       printf "line %d to %d is %d bytes\n", sl, j-1, bc 
       sl=lines[i]+1 
      }  
}' lines.txt data.txt 
line 1 to 100 is 1392 bytes 
line 101 to 200 is 1500 bytes 
line 201 to 300 is 1500 bytes 
line 301 to 360 is 900 bytes 
line 361 to 10000 is 153602 bytes 
line 10001 to 50000 is 680000 bytes 
+0

Vielen Dank! Du hast es gelöst :) – Verthandi

0

Einfache Verbesserung. Niemals innerhalb eine Schleife mit >> umleiten, was außerhalb einer Schleife mit >> umgeleitet werden kann. Schlimmer noch:

while read line 
do 
    # .... stuff omitted ... 
    echo "\"plans.txt.${offSet}.${endByte}/\"" >> lobs.in 
    # .... 
done < line_numbers.txt 

Beachten Sie, wie die einzige Zeile in der Schleife, die alles gibt echo ist. Besser:

+1

Nimm nicht an, Lobs.in 'ist leer vor der Schleife; Verwenden Sie '' 'auch außerhalb der Schleife. – chepner

+0

@chepner, Danke, korrigiert. – agc