Powiązane, ale nie zadowalające odpowiedzi: Jak mogę podzielić duży plik tekstowy na około 500 słów?
Próbuję pobrać plik tekstowy ( http://mattmahoney.net/dc/text8.zip ) zawierający> 10 ^ 7 słów w jednym wierszu i podzielić go na wiersze z N słowami w każdym. Moje obecne podejście działa, ale jest dość powolne i brzydkie (przy użyciu skryptu powłoki):
i=0
for word in $(sed -e 's/\s\+/\n/g' input.txt)
do
echo -n "${word} " > output.txt
let "i=i+1"
if [ "$i" -eq "1000" ]
then
echo > output.txt
let "i=0"
fi
done
Wszelkie wskazówki, w jaki sposób mogę uczynić to szybszym lub bardziej kompaktowym?
text-processing
sed
awk
split
Cory Schillaci
źródło
źródło
Odpowiedzi:
Zakładając, że twoja definicja słowa jest sekwencją niepustych znaków oddzielonych spacjami, oto
awk
rozwiązanie dla pliku jednowierszowegoźródło
Użyj
xargs
(17 sekund):Wykorzystuje
-n
flagę,xargs
która określa maksymalną liczbę argumentów. Wystarczy zmienić1000
się500
lub cokolwiek chcesz ograniczyć.Zrobiłem plik testowy zawierający 10 ^ 7 słów:
Oto statystyki czasowe:
źródło
xargs
„s cytat złuszczaniu zachowanien
wolniej to będzie, tak więc wiesz. Z-n10
anulowałem to po około 8 minutach oczekiwania ...Perl wydaje się w tym zadziwiająco dobry:
Utwórz plik zawierający 10 000 000 słów oddzielonych spacjami
Teraz perl, aby dodać nowy wiersz po każdym 1000 słów
wyczucie czasu
sprawdź wyniki
Zaakceptowane rozwiązanie awk zajęło mi nieco ponad 5 sekund w moim pliku wejściowym.
źródło
Niezbyt przydatne, gdy
N
liczba słów jest dużą liczbą, ale jeśli jest to mała liczba (i idealnie, jeśli nie ma spacji początkowych / końcowych w pliku jednowierszowym), powinno to być dość szybkie (np. 5 słów w wierszu):źródło
paste
ciąg w locie. Na przykład:tr -s '[[:blank:]]' '\n' < text8 | paste -d' ' $(perl -le 'print "- " x 1000')
set
etc ... i nawet wtedy istnieje maksymalna liczba argumentów specyficznych dla systemu (nie znam wszystkich smaków,paste
ale Myślę, że z niektórych implementacjach istnieją ograniczenia co do żadnego z args / plików wejściowych i / lub wyjściowej długości linii ...).To samo polecenie sed można uprościć, określając, ile wzorców przestrzeni słów chcesz dopasować. Nie miałem żadnych dużych plików ciągów do przetestowania, ale bez pętli w oryginalnym skrypcie powinno to działać tak szybko, jak twój procesor może przesyłać strumieniowo dane. Dodatkowa korzyść, będzie działać równie dobrze na plikach wieloliniowych.
źródło
Czcigodne
fmt(1)
polecenie, choć nie działa ściśle na „określonej liczbie słów”, może dość szybko zawijać długie linie do określonej szerokości celu (lub maksymalnej):Lub z nowoczesnym perlem, dla określonej liczby słów, powiedzmy 10, i przyjmując pojedynczą spację jako granicę słowa:
źródło
Polecenie coreutils
pr
to kolejny kandydat: jedynym pomarszczeniem wydaje się być konieczność wymuszenia, aby szerokość strony była wystarczająco duża, aby pomieścić szerokość wyjściową.Korzystając z pliku utworzonego za pomocą generatora 10 000 000 słów @ Glenn_Jackman,
gdzie liczby są potwierdzane w następujący sposób
[Rozwiązanie Perla Glenna jest wciąż trochę szybsze, ~ 1,8 s na tym komputerze].
źródło
w Go spróbowałbym tego w ten sposób
źródło