2012-06-25 13 views
5

Mam plik tekstowy zaczynający się od 9 cyfr kodu uczelni i kończący się 5-cyfrowym kodem kursu.Scal 2 linie w jeden

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 

Istnieje kilka pozycji, w których występuje podział wiersza, jak pokazano w 3 przykładzie powyżej. muszę połączyć 3 i 4 linii na jeden, tak jak 1 i 2 linii, tak, że można łatwo użyć polecenia jak grep, awk itp

Aktualizacja:

odpowiedź Kevina nie wydają się działać.

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] $ /' # nie działa – shantanuo

Odpowiedz

1

Jeśli chodzi o linie podziału: Ten skrypt sed zakłada, że ​​masz co najmniej jedną spację po numerze wiodącym (w pierwszym wierszu podziału) i jedną spację przed końcowym numerem (w ostatnim wierszu podziału), i że istnieje tylko jeden podział na linię podziału.

Zmodyfikowano, aby akceptować dane wejściowe z nowymi liniami Windows CRLF lub * nix LF. należy jednak pamiętać, że wyjście jest * nix \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}' 

lub krócej, ale może mniej czytelny:

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

I należy się spodziewać, że pierwszy z nich jest szybszy, ponieważ najczęstszą testowy (dla pełne linie) obejmuje tylko jedno wyrażenie regularne, natomiast drugi (krótszy) skrypt wymaga dwóch testów wyrażeń regularnych dla najczęstszych testów.

To jest wyjście, które otrzymuję; stosując 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

# Nie działa z przykładami pokazanymi w pytaniu. ## sed version 4.1.5 – shantanuo

+0

To dziwne; to działa dla mnie (dodałem wersję wyjściową i wersję sed do odpowiedzi). Czy wyświetla komunikat o błędzie, czy po prostu nie produkuje pożądanego wyjścia? (może nie obsługuje rozszerzonego regex swithc '-r' ??) –

+0

Czy plik ma normalne * nix' \ n' nowe linie (kontra Windows '\ r \ n' lub może nawet stary Mac' \ r')? Podczas przetwarzania plików generowanych przez system Windows napotykałem na problemy. –

0

Może spróbuj usunąć wszystkie łamanie wierszy, które występują po przecinkami, tak jak poniżej:

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

może chcesz zezwolić na przestrzeni po przecinkami:

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

podział wiersza nie ma potrzeby występować po przecinkach. – shantanuo

1

Zakładając, że dane znajdują się w "pliku.txt", tutaj jest skan, który z powrotem umieściłby linie:

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

Zakłada się, że wszystkie ważne zapisy zaczynają się od liczb 9-cyfrowych. "Chomp" usuwa początkowo nową linię, a wzorzec decyduje o tym, gdzie w wyjściu powinien pojawić się nowy wiersz.

1

To może pracować dla Ciebie:

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

Objaśnienie:

  • Jeśli linia nie kończy się w przestrzeni, a następnie przez pięć cyfr, a następnie dziewięciu cyfr, a następnie spację, usuń znak nowej linii.

EDIT:

dane Test:

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

Wygląda na to, że nie działa z drugim przykładem powyżej. Pytanie zaktualizowane. – shantanuo

+0

@shantanuo przetestowane przy użyciu twoich nowych danych (zobacz EDIT) wydaje mi się w porządku. – potong

0

spróbować tej

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

Nie działa z pierwszym przykładowym plikiem pokazanym w pytaniu. – shantanuo

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

Działa to z drugim przykładem, ale nie z pierwszym. – shantanuo

+0

@shantanuo: Pierwszy to ten, z którym testowałem i działa dobrze dla mnie. Ponadto, gdy podłączę go do 'wc -l', otrzymam 3. –

+0

Awk 3.1.5 zwraca 4 wiersze zamiast 3 – 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

działa z zawartymi danymi określonymi przez zakładając ważne zapisy kończą w ith pięć cyfr:

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 

wyjściowa:

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

Twój wyrażeń' s/([^ \ d] {5}) \ n/$ 1/sg; 'powinno być' s/^ (\ d {9}. *?) (\ n) [^ \ d {5} \ n]/$ 1/gm; 'ponieważ jeśli linia znajdzie numer ** z 5 cyframi w pomiędzy linią ** i linią tam (w rzeczywistości tak), wtedy twoje wyrażenie nie powiedzie się. Dla przykładu: rozważ przerwanie w '61220' w drugiej linii. –