2012-06-25 1 views
5

Ich habe eine Textdatei beginnt mit 9 Ziffern College-Code und endet mit 5 Ziffern Kurscode.Merge 2 Zeilen zu einem

512161000 EN5121 K. K. Jorge Institute of Engineering Education and Research, Nashik 61220 Mechanical Engineering [Second Shift] XOPENH 1 116 16978 
517261123 EN5172 R. C. Rustom Institute of Technology, Shirpur 61220 Mechanical Engineering [Second Shift] YOPENH 1 100 29555 
617561234 EN6175 abc xyz Education Trust, abc xyz College of Engineering, 
Pune 61220 Mechanical Engineering [Second Shift] ZOPENH 2 105 25017 

Es gibt einige Einträge, bei denen es einen Zeilenumbruch gibt, wie im obigen Beispiel 3 gezeigt. brauche ich wie 1. und 2. Zeile nur 3. und 4. Zeile zu einem verschmelzen, so dass ich leicht Befehl wie grep verwenden können, awk usw.

Update:

Kevins Antwort scheint nicht zu funktionieren.

cat todel.txt 
112724510 EN1127 Jagadambha Bahuuddeshiya Gramin Vikas Sanstha's Jagdambha College of, 
Engineering and Technology, Yavatmal 24510 Computer Engineering LSCO 1 55 93531 

cat todel.txt | perl -ne 'chomp; if (/^\d{9}/) { print "\n$_" } else { print "$_\n" }' 
Engineering and Technology, Yavatmal 24510 Computer Engineering LSCO 1 55 93531ege of, 
+0

awk '/^[0-9] /,/[0-9]/$' # nicht – shantanuo

Antwort

1

In Bezug auf geteilte Linien: Dieses Skript sed nimmt an, dass Sie mindestens ein Leerzeichen nach der führenden Nummer (in der ersten Zeile der Teilung) und ein Leerzeichen vor der abschließenden Zahl (in der letzten Zeile der Teilung) haben. und dass es nur eine Aufteilung pro Trennlinie gibt.

Geändert, um Eingaben mit Windows CRLF Zeilenumbrüche zu akzeptieren oder * nix LF. aber beachten Sie, dass der Ausgang ein * nichts \n

sed -nr 's/\r?$// # allow for '\r\n' newlines 
     /^([0-9]{9}) .* ([0-9]{5})$/{p;b} 
     /^([0-9]{9}) /{h;b} 
     /([0-9]{5})$/{x;G; s/\n//; p}' 

oder, kürzer, aber vielleicht weniger lesbar:

sed -nr 's/\r?$//; /^([0-9]{9}) /{/ ([0-9]{5})$/{p;b};h;b};/ ([0-9]{5})$/{x;G; s/\n//; p}' 

Ich erwarte, dass die erste ist schneller, weil der häufigste Test (für Vollzeilen) beinhaltet nur eine einzige Regex, während das zweite (kürzere) Skript zwei Regex-Tests für den häufigsten Test benötigt.

Dies ist der Ausgang, den ich bekomme; mit GNU sed 4.2.1

512161000 EN5121 K. K. Jorge Institute of Engineering Education and Research, Nashik 61220 Mechanical Engineering [Second Shift] XOPENH 1 116 16978 
517261123 EN5172 R. C. Rustom Institute of Technology, Shirpur 61220 Mechanical Engineering [Second Shift] YOPENH 1 100 29555 
617561234 EN6175 abc xyz Education Trust, abc xyz College of Engineering,Pune 61220 enter code hereMechanical Engineering [Second Shift] ZOPENH 2 105 25017 
112724510 EN1127 Jagadambha Bahuuddeshiya Gramin Vikas Sanstha's Jagdambha College of,Engineering and Technology, Yavatmal 24510 Computer Engineering LSCO 1 55 93531 
+0

# Funktioniert nicht mit den in der Frage gezeigten Beispielen. ## sed Version 4.1.5 – shantanuo

+0

Das ist seltsam; es funktioniert für mich (ich habe Ausgabe und sed Version hinzugefügt, um zu antworten) .. Gibt es eine Fehlermeldung, oder einfach nicht die gewünschte Ausgabe zu produzieren? (vielleicht behandelt es nicht den erweiterten Regex-Schalter '-r' ??) –

+0

Hat die Datei normale * nix' \ n'-Zeilenumbrüche (vs. Windows '\ r \ n' oder vielleicht sogar den alten Mac' \ r') Bei der Verarbeitung von Windows-Dateien bin ich auf Probleme gestoßen. –

0

Vielleicht versuchen, alle Zeilenumbrüche zu entfernen, die nach dem Komma auftreten, etwa so:

perl -i -pe 's/,\n/,/g' file.txt 

vielleicht Sie Leerzeichen nach den Kommas zulassen möchten:

perl -i -pe 's/(,\s*)\n/$1/g' file.txt 
+1

Zeilenumbruch funktioniert nicht notwendig auftreten nach Kommas. – shantanuo

1

Angenommen, Ihre Daten sind in "file.txt", hier ist ein Scan, der die Zeilen wieder zusammenfügen würde:

cat file.txt | perl -ne 'chomp; if (/^\d{9}/) { print "\n$_" } else { print "$_\n" }' 

Dies setzt voraus, dass alle gültigen Datensätze mit 9-stelligen Zahlen beginnen. Der "chomp" entfernt die neue Zeile zunächst und das Muster entscheidet, wo eine neue Zeile in der Ausgabe erscheinen soll.

1

Dies könnte für Sie arbeiten:

sed ':a;$!N;/ [0-9]\{5\}\n[0-9]\{9\} /!s/\n//;ta;P;D' file 

Erläuterung:

  • Wenn die Linie endet in einem Raum nicht von fünf Ziffern gefolgt von neun Ziffern gefolgt und dann ein Leerzeichen entfernen Sie den Zeilenumbruch.

EDIT:

Testdaten:

cat <<\! >/tmp/codel.txt 
> 112724510 EN1127 Jagadambha Bahuuddeshiya Gramin Vikas Sanstha's Jagdambha College of, 
> Engineering and Technology, Yavatmal 24510 Computer Engineering LSCO 1 55 93531 
> ! 
sed ':a;$!N;/\s[0-9]\{5\}\n[0-9]\{9\}\s/!s/\n//;ta;P;D' /tmp/codel.txt 
112724510 EN1127 Jagadambha Bahuuddeshiya Gramin Vikas Sanstha's Jagdambha College of,Engineering and Technology, Yavatmal 24510 Computer Engineering LSCO 1 55 93531 
sed ':a;$!N;/\s[0-9]\{5\}\n[0-9]\{9\}\s/!s/\n//;ta;P;D' /tmp/{codel.txt,codel.txt,codel.txt} 
112724510 EN1127 Jagadambha Bahuuddeshiya Gramin Vikas Sanstha's Jagdambha College of,Engineering and Technology, Yavatmal 24510 Computer Engineering LSCO 1 55 93531 
112724510 EN1127 Jagadambha Bahuuddeshiya Gramin Vikas Sanstha's Jagdambha College of,Engineering and Technology, Yavatmal 24510 Computer Engineering LSCO 1 55 93531 
112724510 EN1127 Jagadambha Bahuuddeshiya Gramin Vikas Sanstha's Jagdambha College of,Engineering and Technology, Yavatmal 24510 Computer Engineering LSCO 1 55 93531 
+0

Scheint nicht mit dem zweiten Beispiel oben zu arbeiten. Frage aktualisiert – shantanuo

+0

@shantanuo getestet mit Ihren neuen Daten (siehe EDIT) scheint mir gut. – potong

0

versuchen, diese

sed '/^[0-9]\{9\}/{h;};/^[0-9]\{9\}/!{x;G;s/\n//g;}' test | grep -E '[0-9]{5}$' 
+0

Funktioniert nicht mit der ersten Beispieldatei, die in der Frage angezeigt wird. – shantanuo

0
awk '! ($1 ~ /^[[:digit:]]/) {$0 = save " " $0} $1 ~ /^[[:digit:]]/ {save = $0} $NF ~ /[[:digit:]]$/ {print}' inputfile 
+0

Dies funktioniert mit dem zweiten Beispiel, aber nicht mit dem ersten. – shantanuo

+0

@shantanuo: Die erste ist die, die ich getestet habe und es funktioniert gut für mich. Wenn ich es an 'wc -l' übergebe, bekomme ich 3. –

+0

Awk 3.1.5 gibt 4 Zeilen statt 3 zurück – shantanuo

0
cat todel.txt |awk 'BEGIN {i=0} {first[i]=$1; lines[i++] = $0;} END {for (x=0; x<i; x++) { if (x==(i - 1) || (first[x + 1] ~ /^[0-9]+$/ && length(first[x + 1])==9)) {printf("%s: %s\n", x, lines[x]);} else {printf("%s: %s%s\n", x, lines[x], lines[x + 1]); x++;} } }' 
0

Das mit den enthaltenen Daten arbeitet gesetzt durch die Annahme gültig Aufzeichnungen enden w ith fünf Ziffern:

use Modern::Perl; 

my $data = do{local $/; <DATA>}; 
$data =~ s/([^\d]{5})\n/$1 /sg; 
say $data; 


__DATA__ 
512161000 EN5121 K. K. Jorge Institute of Engineering Education and Research, Nashik 61220 Mechanical Engineering [Second Shift] XOPENH 1 116 16978 
517261123 EN5172 R. C. Rustom Institute of Technology, Shirpur 61220 Mechanical Engineering [Second Shift] YOPENH 1 100 29555 
617561234 EN6175 abc xyz Education Trust, abc xyz College of Engineering, 
Pune 61220 Mechanical Engineering [Second Shift] ZOPENH 2 105 25017 
112724510 EN1127 Jagadambha Bahuuddeshiya Gramin Vikas Sanstha's Jagdambha College of, 
Engineering and Technology, Yavatmal 24510 Computer Engineering LSCO 1 55 93531 

Ausgang:

512161000 EN5121 K. K. Jorge Institute of Engineering Education and Research, Nashik 61220 Mechanical Engineering [Second Shift] XOPENH 1 116 16978 
517261123 EN5172 R. C. Rustom Institute of Technology, Shirpur 61220 Mechanical Engineering [Second Shift] YOPENH 1 100 29555 
617561234 EN6175 abc xyz Education Trust, abc xyz College of Engineering, Pune 61220 Mechanical Engineering [Second Shift] ZOPENH 2 105 25017 
112724510 EN1127 Jagadambha Bahuuddeshiya Gramin Vikas Sanstha's Jagdambha College of, Engineering and Technology, Yavatmal 24510 Computer Engineering LSCO 1 55 935315 
+0

Deine Regex' s/([^ \ d] {5}) \ n/$ 1/sg; 'sollte' s/^ (\ d {9}. *?) (\ n) [^ \ d {5} \ n]/$ 1/gm; 'weil, wenn die Zeile eine ** Nummer mit 5 Ziffern in findet zwischen der Linie ** und wenn die Linie dort bricht (was tatsächlich der Fall ist), würde Ihre Regex scheitern. Für ex: in Betracht ziehen brechen bei '61220' in der zweiten Zeile. –