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ąć. Wpisy ( [ entry*]
gdzie gdzie *
jest liczbą całkowitą) są zawsze w kolejności numerycznej i są kolejnymi liczbami całkowitymi zaczynającymi się od 1 do N (w moim rzeczywistym pliku wejściowym, N = 200001).
Czy jest jakiś sposób na automatyczne dzielenie plików tekstowych w bash? Moje rzeczywiste wejście entry.txt
faktycznie zawiera 200 001 wpisów.
źródło
match
wpisywać:/^\[/ { name=$2 }
powinno wystarczyć.[ blahblah blah blah ]
w mojej odpowiedzi.FS
, np-F '\\[ | \\]'
.#S x
, gdzie x jest liczbą 1, 2 lub 3 cyfr. Wystarczy zapisać je w x.dat. Próbowałem:gawk '/^#S/{match($0, / [0-9]* /, k)} {print >k[1]".dat" }' myFile.txt
i kilka jego odmian.gawk '/^#S/{match($0, /^#S (\s+?)([0-9]+)(\s+?)/, k)} {print >k[2]".txt" }' test.txt
rację.2
Jednak nie rozumiem zbyt dobrze numeru tablicy .Z csplit z GNU coreutils ( niewbudowany Linux, Cygwin):
Otrzymasz dodatkowy pusty plik
entry0.txt
(zawierający część przed pierwszym nagłówkiem).Standardowy csplit nie ma
{*}
nieokreślonego repeatera i-b
opcji określania formatu sufiksu, więc w innych systemach musisz najpierw policzyć liczbę sekcji, a potem zmienić nazwy plików wyjściowych.źródło
W Perlu można to zrobić znacznie prościej:
źródło
Oto krótki linijka awk:
Jak to działa?
/^\[/
dopasowuje linie zaczynające się od lewego nawiasu kwadratowego, oraz{ofn=$2 ".txt"}
ustawia zmienną na drugie słowo rozdzielane białymi odstępami jako naszą nazwę pliku wyjściowego. Następnie,ofn
to warunek, który ma wartość true, jeśli zmienna jest ustawiona (powoduje to, że wiersze przed pierwszym nagłówkiem zostaną zignorowane){print > ofn}
przekierowuje bieżącą linię do określonego pliku.Zauważ, że wszystkie spacje w tym skrypcie awk można usunąć, jeśli zwartość cię uszczęśliwia.
Zauważ również, że powyższy skrypt naprawdę potrzebuje nagłówków sekcji, aby mieć spacje wokół siebie, a nie w nich. Jeśli chcesz mieć możliwość obsługi nagłówków sekcji takich jak
[foo]
i[ this that ]
, potrzebujesz jeszcze trochę więcej kodu:Używa
sub()
funkcji awk do usuwania wiodących i końcowych nawiasów kwadratowych plus białych znaków. Zauważ, że zgodnie ze standardowym zachowaniem awk spowoduje to zwinięcie białych znaków (separatora pól) w jedną spację (tzn. Zostanie[ this that ]
zapisany"this that.txt"
). Jeśli zachowanie oryginalnych białych znaków w wyjściowych nazwach plików jest ważne, możesz eksperymentować, ustawiając FS.źródło
Można to zrobić z wiersza poleceń w pythonie jako:
źródło
Jest to dość prymitywny, ale łatwy do zrozumienia sposób: użyj,
grep -l '[ entry ]' FILENAME
aby podzielić numery linii na [entry]. Użyj kombinacji z głową i ogonem, aby uzyskać odpowiednie kawałki.Tak jak powiedziałem; nie jest ładny, ale łatwo go zrozumieć.
źródło
Co powiesz na użycie awk z
[
jako separatora rekordów i spacji jako separatora pól. Daje nam to łatwo dane do umieszczenia w pliku jako miejsce, w$0
którym musi on umieścić z powrotem usunięte wiodące[
i nazwę pliku jako$1
. Musimy wtedy poradzić sobie tylko ze specjalnym przypadkiem pierwszego rekordu, który jest pusty. To daje nam:źródło
Odpowiedź terdona działa dla mnie, ale musiałem używać gawk, a nie awk. Podręcznik gawk (wyszukiwanie „match (”) wyjaśnia, że argument tablicy w match () jest rozszerzeniem gawk. Może to zależy od instalacji Linuksa i wersji awk / nawk / gawk, ale na mojej maszynie Ubuntu tylko gawk działał znakomicie odpowiedź:
źródło
Oto rozwiązanie perla. Ten skrypt wykrywa
[ entryN ]
linie i odpowiednio zmienia plik wyjściowy, ale nie sprawdza, nie analizuje ani nie przetwarza danych w każdej sekcji, po prostu drukuje linię wejściową do pliku wyjściowego.źródło
Cześć. Napisałem ten prosty skrypt, używając ruby, aby rozwiązać problem
możesz użyć tego w ten sposób:
przetestowałem to i działa dobrze ..
źródło
Wolę tę
csplit
opcję, ale alternatywą jest rozwiązanie awk GNU:parse.awk
Uruchom tak:
źródło
RT
zmienna wydaje się być specyficzna dla gawk. To rozwiązanie nie działa dla mnie przy użyciu awk FreeBSD.