Zgadzam się z tobą - to prawdopodobnie jest to ogólny problem. Jednak niektóre popularne narzędzia mają pewne funkcje do obsługi tego.
nl
nl
, na przykład, dzieli dane wejściowe na strony logiczne, które są -d
eliminowane przez dwuznakowy separator sekcji . Trzy zdarzenia na linii same w sobie wskazują początek kursu , dwa ciała i jeden stopkę . Zastępuje wszystkie znalezione na wejściu puste linie wyjściowe - które są jedynymi pustymi liniami, jakie kiedykolwiek drukuje
Zmieniłem twój przykład, aby dołączyć inną sekcję i wstawić go ./infile
. Wygląda to tak:
line A
line B
@@inline-code-start
line X
line Y
line Z
@@inline-code-end
line C
line D
@@start
line M
line N
line O
@@end
Następnie wykonałem następujące czynności:
sed 's/^@@.*start$/@@@@@@/
s/^@@.*end$/@@/' <infile |
nl -d@@ -ha -bn -w1
nl
można powiedzieć, aby gromadził stan na logicznych stronach, ale domyślnie tak nie jest. Zamiast tego numeruje wiersze danych wejściowych według stylów i według sekcji . Tak więc -ha
środki ponumerować wszystkie nagłówki wierszy i -bn
oznacza brak linii nadwozia - jak zaczyna się w organizmie stanie.
Dopóki się tego nie nauczyłem, używałem nl
dowolnego wejścia, ale po uświadomieniu sobie, że nl
może to zniekształcić dane wyjściowe zgodnie z domyślnym -d
eliminatorem \:
, nauczyłem się być bardziej ostrożnym i zacząłem używać grep -nF ''
zamiast tego nieprzetestowanego wejścia. Ale kolejną lekcją wyciągniętą tego dnia było to, że nl
można bardzo użytecznie zastosować pod innymi względami - takimi jak ten - jeśli tylko zmodyfikujesz jego dane wejściowe tylko nieznacznie - tak jak ja sed
powyżej.
WYNIK
line A
line B
1 line X
2 line Y
3 line Z
line C
line D
1 line M
2 line N
3 line O
Oto kilka więcej informacji nl
- czy zauważysz powyżej, jak wszystkie wiersze oprócz ponumerowanych zaczynają się od spacji? Kiedy nl
linie liczb wstawiają określoną liczbę znaków do nagłówka każdego z nich. W przypadku tych wierszy nie jest numerowany - nawet puste - zawsze dopasowuje wcięcie, wstawiając ( idth -w
count + -s
eparator len) * spacje na początku nienumerowanych linii. Pozwala to na dokładne odtworzenie treści nienumerowanej przez porównanie jej z treścią numerowaną - przy niewielkim wysiłku. Jeśli weźmiesz pod uwagę, że nl
podzieli on twoje dane wejściowe na logiczne sekcje i że możesz wstawić dowolne -s
ciągi na początku każdej linii, którą numeruje, to całkiem łatwo jest obsłużyć wynik:
sed 's/^@@.*start$/@@@@@@/
s/^@@.*end/@@/; t
s/^\(@@\)\{1,3\}$/& /' <infile |
nl -d@@ -ha -bn -s' do something with the next line!
'
Powyższe wydruki ...
line A
line B
1 do something with the next line!
line X
2 do something with the next line!
line Y
3 do something with the next line!
line Z
line C
line D
1 do something with the next line!
line M
2 do something with the next line!
line N
3 do something with the next line!
line O
GNU ANTYLOPA sed
Jeśli nl
nie jest twoją aplikacją docelową, GNU sed
może e
wykonać dowolne polecenie powłoki w zależności od dopasowania.
sed '/^@@.*start$/!b
s//nl <<\\@@/;:l;N
s/\(\n@@\)[^\n]*end$/\1/
Tl;e' <infile
Powyżej sed
zbiera dane wejściowe w przestrzeni wzorów, dopóki nie będzie wystarczające, aby pomyślnie przejść podstawienie T
est i przestać b
biegać z powrotem do :l
abla. Kiedy tak się dzieje, wykonuje e
polecenia nl
wejściowe reprezentowane jako <<
dokument tutaj dla całej reszty przestrzeni wzorcowej.
Przepływ pracy wygląda następująco:
/^@@.*start$/!b
- jeśli
^
cała linia $
ma !
nie /
pasuje /
powyższy wzór, to jest b
ranczerskich z skryptu i autoprinted - więc od tej chwili pracujemy tylko z serią linii, która rozpoczęła się z wzoru.
s//nl <<\\@@/
- puste
s//
pole /
oznacza ostatni adres, który sed
próbowano dopasować - więc to polecenie zastępuje zamiast tego całą @@.*start
linię nl <<\\@@
.
:l;N
:
Polecenie definiuje etykietę oddział - tu ustawić jeden o nazwie :l
Abel. Polecenie N
ext dołącza następny wiersz danych wejściowych do obszaru wzorów, po którym \n
następuje znak ewline. Jest to jeden z niewielu sposobów, aby uzyskać \n
ewline w sed
przestrzeni wzorów - \n
postać ewline jest pewnym ogranicznikiem dla sed
der, który robił to jakiś czas.
s/\(\n@@\)[^\n]*end$/\1/
- ta
s///
ubstytucja może się powieść tylko po napotkaniu początku i tylko przy pierwszym wystąpieniu linii końcowej . Będzie działał tylko na przestrzeni wzorów, w której \n
natychmiast po ostatniej linii ewline zostanie @@.*end
zaznaczony sam koniec $
przestrzeni wzorów. Kiedy działa, zastępuje cały dopasowany ciąg \1
pierwszą \(
grupą \)
lub \n@@
.
Tl
- te
T
gałęzie dowodzenia est na etykiecie (jeżeli istnieje) , czy udane podstawienie nie nastąpiło od czasu ostatniego linia wejściowa została wciągnięta w przestrzeń wzoru (tak jak ja w / N
) . Oznacza to, że za każdym razem, gdy \n
ewline jest dodawana do przestrzeni wzorów, która nie pasuje do ogranicznika końcowego, T
polecenie est kończy się niepowodzeniem i rozgałęzia się z powrotem do :l
abla, co powoduje sed
ciągnięcie N
linii zewnętrznej i zapętlanie aż do pomyślnego zakończenia .
e
Gdy podstawienie na mecz końcowego jest udany, a skrypt nie oddział z powrotem dla nieudanej T
est, sed
będą e
xecute polecenie, które l
ooks tak:
nl <<\\@@\nline X\nline Y\nline Z\n@@$
Możesz to zobaczyć, edytując ostatnią linię, aby wyglądała Tl;l;e
.
Drukuje:
line A
line B
1 line X
2 line Y
3 line Z
line C
line D
1 line M
2 line N
3 line O
while ... read
Ostatnim sposobem, a może najprostszym, jest użycie while read
pętli, ale nie bez powodu. Powłoka - (szczególnie bash
powłoka) - jest zazwyczaj dość fatalna w obsłudze dużych ilości lub stałych strumieni. To też ma sens - zadaniem powłoki jest obsługa znaków po znaku i wywoływanie innych poleceń, które mogą obsłużyć większe rzeczy.
Ale co ważne, jego rola polega na tym, że powłoka nie może read
przesadzać z danymi wejściowymi - jest określona, aby nie buforować danych wejściowych lub wyjściowych do momentu, w którym zużywa tak dużo lub nie przekazuje wystarczająco dużo czasu, aby wywoływać polecenia, których nie ma - do bajtu. read
Stanowi więc doskonały test wejściowy - do return
informacji o tym, czy jest jeszcze wejście i powinieneś wywołać następne polecenie, aby je odczytać - ale ogólnie nie jest to najlepsza droga.
Oto przykład, jednak, jak można wykorzystać read
i inne polecenia do wejścia procesu synchronizacji:
while IFS= read -r line &&
case $line in (@@*start) :;; (*)
printf %s\\n "$line"
sed -un "/^@@.*start$/q;p";;
esac;do sed -un "/^@@.*end$/q;=;p" |
paste -d: - -
done <infile
Pierwszą rzeczą, która dzieje się dla każdej iteracji, jest read
ciągnięcie linii. Jeśli się powiedzie, oznacza to, że pętla nie uderzyła jeszcze w EOF, a więc w case
dopasowaniu ogranicznika początkowegodo
blok jest natychmiast wykonywany. W przeciwnym razie printf
drukuje $line
go read
i sed
nazywa się.
sed
będzie p
rintować każdą linię, aż napotka znacznik początkowy - kiedy q
całkowicie wykorzysta wejście. -u
Przełącznik nbuffered jest konieczne dla GNU sed
ponieważ może buforować dość łapczywie inaczej, ale - według specyfikacji - inne POSIX sed
s powinno działać bez szczególną uwagę - tak długo, jak <infile
jest zwykłym plikiem.
Gdy pierwsze sed
q
uituje, powłoka wykonuje do
blok pętli - która wywołuje kolejną, sed
która wypisuje każdą linię, aż napotka znacznik końca . Potokuje dane wyjściowe do paste
, ponieważ wypisuje numery linii w osobnych wierszach. Lubię to:
1
line M
2
line N
3
line O
paste
następnie wkleja je razem do :
postaci, a cały wynik wygląda następująco:
line A
line B
1:line X
2:line Y
3:line Z
line C
line D
1:line M
2:line N
3:line O
To tylko przykłady - tutaj można wykonać wszystko w teście lub wykonać bloki, ale pierwsze narzędzie nie może zużywać zbyt wiele danych wejściowych.
Wszystkie zaangażowane narzędzia odczytują te same dane wejściowe - i drukują wyniki - każde z osobna. Tego rodzaju rzeczy może być trudno się zawiesić - ponieważ różne narzędzia będzie buforować więcej niż inni - ale można ogólnie polegać na dd
, head
i sed
zrobić to, co trzeba (choć dla GNU sed
, trzeba CLI-switch) i zawsze powinieneś być w stanie polegać read
- ponieważ z natury jest bardzo powolny . I dlatego powyższa pętla wywołuje ją tylko raz na blok wejściowy.
nl
nie musi gromadzić stanu . Spójrz nanl -d
i sprawdzićman
/info
stron zawierających informacje onl
„s sekcja separatora .