2011-10-20 16 views
11

Potrzebuję wybrać kilka liczb z niektórych plików tekstowych. Mogę wybrać linie, których potrzebuję z grep, ale nie wiedziałem, jak wyodrębnić liczby z linii. Kolega pokazał mi, jak to zrobić z bash z Perl:Python odpowiednik perl -pe?

cat results.txt | perl -pe 's/.+(\d\.\d+)\.\n/\1 /' 

Jednak zazwyczaj kodu w Pythonie, nie Perl. Moje pytanie brzmi, czy mogłem używać Pythona w ten sam sposób? Czy mógłbym przekazać coś od Basha do Pythona, a następnie otrzymać wynik prosto do stdout? ... Jeśli to ma sens. A może Perl jest po prostu wygodniejszy w tym przypadku?

+1

Możesz ponownie rozważyć i po prostu zrobić wszystkie parsowania w Pythona. Byłoby szalenie łatwe, aby zrobić greping z Pythona. Jeśli masz problemy, po prostu dodaj kolejne pytanie "jak wypakować te linie w pythonie", a 5 minut później otrzymasz kod: – TJD

+0

@ TJD: Całkowicie się zgadzam. – heltonbiker

+0

@TJD: Prawda. Rozważę to. – Nagel

Odpowiedz

9

Tak, można użyć Pythona z linii poleceń. python -c <stuff> będzie działać jako <stuff> jako kod Pythona. Przykład:

python -c "import sys; print sys.path" 

Nie jest bezpośrednim odpowiednikiem opcji -p Perl (automatyczne przetwarzanie wejście/wyjście line-by-line), ale to głównie dlatego, że Python nie używać tego samego pojęcia $_ i co nie robi Perl - w Pythonie wszystkie wejścia i wyjścia są wykonywane ręcznie (poprzez raw_input()/input() i print/print()).


dla konkretnego przykładu: (.. Oczywiście nieco bardziej nieporęczny To chyba lepiej po prostu napisać skrypt, aby zrobić to w rzeczywistej Pythonie)

cat results.txt | python -c "import re, sys; print ''.join(re.sub(r'.+(\d\.\d+)\.\n', r'\1 ', line) for line in sys.stdin)" 

+0

Ah, dzięki! Byłaś o wiele przed sobą :) – Nagel

+0

Dziwnie, wersja Pythona, którego używam (2.7.1), nie wydaje się lubić wbudowanych pętli 'for' po średnikach - proste polecenia działają, ale bardziej złożone struktury rzucają' SyntaxError'. – duskwuff

+0

@duskwuff - to jest oczekiwane. Średniki nie mają żadnego sposobu na określenie bloków. Zamiast tego możesz użyć wyrażenia ze zrozumieniem/generatora. – Amber

2

Można użyć:

$ python -c '<your code here>' 
+0

Dzięki za szybką odpowiedź (zarówno dla ciebie, jak i @Amber)! To prawie to, czego szukałem, ale nie całkiem. Jest to analogiczne do perl -e, ale nie wypisuje wyjścia na standardowe wyjście. Tak więc 'python -c 2 + 2' nic nie daje. (Możesz użyć 'python -c 'a = 2 + 2; print a'' oczywiście, ale rozumiesz?) – Nagel

+0

@Nagel: wszystkie odpowiedzi dotyczą jakiejś metody wiersza poleceń, ale czy używasz skryptu? (do przeczytania garści plików, na pewno skorzystam ze skryptu) – heltonbiker

0

Można używać Pythona do wykonaj kod bezpośrednio z wiersza poleceń basha, używając python -c lub możesz przetworzyć dane wejściowe wyprowadzane na stdin za pomocą sys.stdin, patrz here.

1

Można teoretycznie, ale Python nie ma prawie tak dużo magii regex jak Perl, więc wynikowe polecenie będzie znacznie bardziej nieporęczne, zwłaszcza że nie można używać wyrażeń regularnych bez importowania re (a ty prawdopodobnie będzie potrzebował również sys dla sys.stdin).

Pythona równoważne z Twojego kolegi Perl jednej liniowej wynosi około:

import sys, re 
for line in sys.stdin: 
    print re.sub(r'.+(\d\.\d+)\.\n', r'\1 ', line) 
+0

Importowanie standardowych modułów nie powinno być uważane za "nieczysty" lub w inny sposób mniej odporny kod, przynajmniej nie w języku Python. – heltonbiker

+0

Dzięki! Podejrzewałem tak samo. Chyba nauczę się podstawowej perl dla tego rodzaju zadania :) – Nagel

+0

@heltonbiker ma punkt oczywiście, ale wynikowy kod Pythona jest dłuższy i wydaje się nieco niewygodny do użycia jako narzędzie wiersza poleceń. – Nagel

1

Masz problem, który można rozwiązać na kilka sposobów.

Myślę, że powinieneś rozważyć użycie wyrażenia regularnego (co robi perl w twoim przykładzie) bezpośrednio z Pythona. Wyrażenia regularne znajdują się w module re. Przykładem może być:

import re 
filecontent = open('somefile.txt').read() 
print re.findall('.+(\d\.\d+)\.$', filecontent) 

(I woleliby używając $ zamiast „\ n” dla zakończeń linii, ponieważ zakończeń linii różnią się między systemami operacyjnymi i kodowania plików)

Jeśli chcesz wywołać bash polecenia z poziomu Pythona można użyć:

import os 
os.system(mycommand) 

Gdzie polecenie jest poleceniem bash.Używam go cały czas, ponieważ niektóre operacje są lepsze do wykonania w bashu niż w Pythonie.

Na koniec, jeśli chcesz wyodrębnić liczby za pomocą grep, użyj opcji -o, która drukuje tylko dopasowaną część.

0

Perl (lub sed) jest wygodniejszy. Jednak możliwe jest, jeśli brzydki:

python -c 'import sys, re; print "\n".join(re.sub(".+(\d\.\d+)\.\n","\1 ", l) for l in sys.stdin)'