Mam plik tekstowy o nazwie, entry.txt
który zawiera następujące elementy:
[ entry1 ]
1239 1240 1242 1391 1392 1394 1486 1487 1489 1600
1601 1603 1657 1658 1660 2075 2076 2078 2322 2323
2325 2740 2741 2743 3082 3083 3085 3291 3292 3294
3481 3482 3484 3633 3634 3636 3690 3691 3693 3766
3767 3769 4526 4527 4529 4583 4584 4586 4773 4774
4776 5153 5154 5156 5628 5629 5631
[ entry2 ]
1239 1240 1242 1391 1392 1394 1486 1487 1489 1600
1601 1603 1657 1658 1660 2075 2076 2078 2322 2323
2325 2740 2741 2743 3082 3083 3085 3291 3292 3294
3481 3482 3484 3690 3691 3693 3766 3767 3769 4526
4527 4529 4583 4584 4586 4773 4774 4776 5153 5154
5156 5628 5629 5631
[ entry3 ]
1239 1240 1242 1391 1392 1394 1486 1487 1489 1600
1601 1603 1657 1658 1660 2075 2076 2078 2322 2323
2325 2740 2741 2743 3082 3083 3085 3291 3292 3294
3481 3482 3484 3690 3691 3693 3766 3767 3769 4241
4242 4244 4526 4527 4529 4583 4584 4586 4773 4774
4776 5153 5154 5156 5495 5496 5498 5628 5629 5631
Chciałbym podzielić ją na trzy pliki tekstowe: entry1.txt
, entry2.txt
, entry3.txt
. Ich zawartość jest następująca.
entry1.txt :
[ entry1 ]
1239 1240 1242 1391 1392 1394 1486 1487 1489 1600
1601 1603 1657 1658 1660 2075 2076 2078 2322 2323
2325 2740 2741 2743 3082 3083 3085 3291 3292 3294
3481 3482 3484 3633 3634 3636 3690 3691 3693 3766
3767 3769 4526 4527 4529 4583 4584 4586 4773 4774
4776 5153 5154 5156 5628 5629 5631
entry2.txt :
[ entry2 ]
1239 1240 1242 1391 1392 1394 1486 1487 1489 1600
1601 1603 1657 1658 1660 2075 2076 2078 2322 2323
2325 2740 2741 2743 3082 3083 3085 3291 3292 3294
3481 3482 3484 3690 3691 3693 3766 3767 3769 4526
4527 4529 4583 4584 4586 4773 4774 4776 5153 5154
5156 5628 5629 5631
entry3.txt :
[ entry3 ]
1239 1240 1242 1391 1392 1394 1486 1487 1489 1600
1601 1603 1657 1658 1660 2075 2076 2078 2322 2323
2325 2740 2741 2743 3082 3083 3085 3291 3292 3294
3481 3482 3484 3690 3691 3693 3766 3767 3769 4241
4242 4244 4526 4527 4529 4583 4584 4586 4773 4774
4776 5153 5154 5156 5495 5496 5498 5628 5629 5631
Innymi słowy, [
znak wskazuje, że nowy plik powinien się rozpocząć.
Czy jest jakiś sposób na automatyczne dzielenie plików tekstowych? Moje ostateczne, rzeczywiste dane wejściowe entry.txt
faktycznie zawierają 200 001 wpisów.
Świetnie byłoby podzielić tekst na Windows lub Linux. Nie mam dostępu do komputera Mac. Dzięki!
Odpowiedzi:
A oto ładny, prosty gawk one-liner:
Będzie to działać dla każdego rozmiaru pliku, niezależnie od liczby linii w każdym wpisie, o ile wygląda nagłówek każdego wpisu
[ blahblah blah blah ]
. Zwróć uwagę na miejsce tuż po otwarciu[
i tuż przed zamknięciem]
.WYJAŚNIENIE:
awk
igawk
czytać plik wejściowy linia po linii. Gdy każdy wiersz jest czytany, jego zawartość jest zapisywana w$0
zmiennej. Mówimy tutaj, aby awk dopasowywał wszystko w nawiasach kwadratowych i zapisywał dopasowanie w tablicyk
.Zatem za każdym razem, gdy wyrażenie regularne jest dopasowane, to znaczy dla każdego nagłówka w pliku, k [1] będzie miał dopasowany region linii. Mianowicie „entry1”, „entry2” lub „entry3” lub „entryN”.
name=k[1]
po prostu zapisuje wartość k [1] (dopasowanie) w nowej zmiennejname
.Na koniec drukujemy każdą linię do pliku o nazwie
<whatever value k currently has>.txt
, tj. Entry1.txt, entry2.txt ... entryN.txt.Ta metoda będzie znacznie szybsza niż Perl dla większych plików.
Nie mogę za to ręczyć, ponieważ nigdy nie korzystałem z powłoki systemu Windows, ale jestem gotów się założyć, że będzie to znacznie szybsze. Gawk / awk są SZYBKIE.
źródło
W przypadku rozwiązania Windows wypróbuj ten skrypt PowerShell:
Edytuj odpowiednio zmienne
$Path
i$InputFile
. Z pewnymi drobnymi modyfikacjami może również zaakceptować te informacje jako parametry wiersza poleceń lub możesz przekształcić je w funkcję.źródło
Jeszcze inne
awk
rozwiązanie:źródło
Następujący skrypt perla wykonuje to zadanie:
Uruchom skrypt w następujący sposób:
Skrypt działa bez względu na to, ile sekcji wejściowych jest zawartych i jak długo sekcje są tak długie, jak tylko nagłówki sekcji wejściowych
[ some text ]
.Jeśli wolisz nieczytelny kod lub po prostu nie chcesz gdzieś przechowywać skryptu, możesz użyć tego pojedynczego polecenia:
źródło
cat
, możesz po prostu biegaćscript.pl test.txt
.STDIN
, nie możesz przekazać pliku tekstowego jako parametru. Jest jednakscript.pl < test.txt
lepsze niż używaniecat
- odpowiednio zaktualizowałem swoją odpowiedź.while(<>)
który bierze plik wejściowy jako pierwszy argument.Czy nie jest łatwiej używać istniejących poleceń? Nie wszystko potrzebuje nowego programu.
plik csplit / \ [/
źródło
csplit
jest właściwym narzędziem do pracy. Musiałem dodać liczbę powtórzeń i zamienić argumenty, aby działało. Poniższy wiersza polecenia zbliżony do tego, co PO poprosił o:csplit -f entry -b '%d.txt' -z entry.txt '/^\[/' '{*}'
.csplit
tylko wtedy, gdy nazwa rekordu w pliku będzie zgodna zeentryXX
wzorcem, ponieważ nie obsługuje ustawiania prefiksów zmiennych