Jeśli istniejące linie komentowane tworzą pojedynczy ciągły blok, możesz zamiast tego dopasować od pierwszej linii komentowanej, komentując tylko te linie aż do wzorca końcowego, który nie został jeszcze skomentowany
sed '/^#/,/dotan/ s/^[^#]/#&/' file
Jeśli istniejące komentarze nie są ciągłe, to z powodu chciwości charakteru dopasowania zakresu sed, myślę, że musisz zrobić coś takiego
tac file | sed '/dotan/,/^#/ s/^[^#]/#&/' | tac
tzn. dopasuj w górę od wzorca końcowego do „pierwszego” komentarza - oczywiście nie jest to tak wygodne, jeśli potrzebujesz rozwiązania na miejscu.
Możesz obsłużyć oba przypadki (wiersze z komentarzem w jednym ciągłym bloku lub przeplatane między wierszami bez komentarza) za pomocą pojedynczego sedwywołania:
sed '1,/PATTERN/{/^#/{x;1d;b};//!{H;/PATTERN/!{1h;d};//{x;s/\n/&#/g}}}' infile
Przetwarza tylko linie w 1,/PATTERN/zakresie. To e xzmiany trzymać przestrzeń w. przestrzeń wzoru za każdym razem, gdy linia jest komentowana (więc w buforze wstrzymania nigdy nie ma więcej niż jedna linia komentowana) i dołącza każdą linię, która nie jest komentowana do Hstarej spacji (gdy jest w pierwszej linii, 1di odpowiednio 1hsą również potrzebne do usunięcia początkowej pusta linia w buforze wstrzymania).
Kiedy osiągnie linię pasującą do WZORCA, dołącza ją również do Hstarego bufora, e xzmienia bufory, a następnie zamienia każdy \nznak ewline w obszarze wzorca \newline i a #(to znaczy, wszystkie linie w obszarze wzorca zaczynają się od #, uwzględnienie pierwszego wiersza jako pierwszego wiersza w przestrzeni wstrzymania jest zawsze komentarzem).
Z próbką infile:
alice
#bob
bill
#charlie
ding
dong
dotan
jimmy
#garry
bieganie:
sed '1,/dotan/{ # if line is in this range -start c1
/^#/{ # if line is commented -start c2
x # exchage hold space w. pattern space
1d # if 1st line, delete pattern space
b # branch to end of script
} # -end c2
//!{ # if line is not commented -start c3
H # append to hold space
/dotan/!{ # if line doesn't match dotan -start c4
1h # if 1st line, overwrite hold space
d # delete pattern space
} # -end c4
//{ # if line matches dotan -start c5
x # exchage hold space w. pattern space
s/\n/&#/g # add # after each newline character
} # -end c5
} # -end c3
}' infile # -end c1
wyjścia:
alice
#bob
bill
#charlie
#ding
#dong
#dotan
jimmy
#garry
więc komentuje tylko wiersze od (i wyklucza) #charliedo (włącznie) dotani pozostawia pozostałe wiersze bez zmian.
Jasne, zakłada to, że przed dopasowaniem linii zawsze jest przynajmniej jedna linia z komentarzem PATTERN. Jeśli tak nie jest, możesz dodać dodatkową kontrolę przed wymianą:/^#/{s/\n/&#/g}
Tak, jak prosisz. Po prostu działa na stosie - buduje go, gdy jest to konieczne i tak długo, jak to konieczne między wystąpieniami komentowanych linii, i zrzuca stary bufor na korzyść nowej komentowanej linii dalej na wejściu, gdy ją znajdzie. Obrazek...
Przepraszam, nie wiem, dlaczego to zrobiłem. Ale przyszło mi do głowy.
W każdym razie sedrozkłada swoje bufory między każdą ostatnią komentowaną linią w dowolnej serii, nigdy nie zatrzymując ani jednego więcej w swoim buforze, niż jest to konieczne do dokładnego śledzenia ostatniego komentowanego wystąpienia, a jeśli w dowolnym momencie napotka ostatnią linię podczas tej operacji, spróbuje końcowa ginstrukcja wykonania gałęzi i odgałęzienie tszacują, że cały bufor zostanie wydrukowany, w przeciwnym razie Pzrzuci wszystkie linie, które zwolni z bufora, gdy tylko to zrobi.
Wydaje mi się, że właśnie to przywodziło na myśl akordeon ...
printf %s\\n \#alice \#bob charlie dotan eric \
\#alice \#bob charlie dotan eric \
\#alice \#bob charlie dotan eric |
sed -e:n -e'l;/\n#.*\ndotan/!{$!{N;/^#/bn' \
-eb -e\} -e'/^#/s/\(\n\)\(dotan.*\)*/\1#\2/g' \
-et -e\} -eP\;D
#alice
#alice\n#bob$
#alice\n#bob\ncharlie$
#alice\n#bob\ncharlie\ndotan$
#alice
#bob\ncharlie\ndotan$
#bob\ncharlie\ndotan\neric$
#bob\ncharlie\ndotan\neric\n#alice$
#bob\ncharlie\ndotan\neric\n#alice\n#bob$
#bob\ncharlie\ndotan\neric\n#alice\n#bob\ncharlie$
#bob\ncharlie\ndotan\neric\n#alice\n#bob\ncharlie\ndotan$
#bob
charlie\ndotan\neric\n#alice\n#bob\ncharlie\ndotan$
charlie
dotan\neric\n#alice\n#bob\ncharlie\ndotan$
dotan
eric\n#alice\n#bob\ncharlie\ndotan$
eric
#alice\n#bob\ncharlie\ndotan$
#alice
#bob\ncharlie\ndotan$
#bob\ncharlie\ndotan\neric$
#bob\ncharlie\ndotan\neric\n#alice$
#bob\ncharlie\ndotan\neric\n#alice\n#bob$
#bob\ncharlie\ndotan\neric\n#alice\n#bob\ncharlie$
#bob\ncharlie\ndotan\neric\n#alice\n#bob\ncharlie\ndotan$
#bob
charlie\ndotan\neric\n#alice\n#bob\ncharlie\ndotan$
charlie
dotan\neric\n#alice\n#bob\ncharlie\ndotan$
dotan
eric\n#alice\n#bob\ncharlie\ndotan$
eric
#alice\n#bob\ncharlie\ndotan$
#alice
#bob\ncharlie\ndotan$
#bob\ncharlie\ndotan\neric$
#bob
#charlie
#dotan
eric
Jest tylko jedna różnica między tym poleceniem a powyższym i jest to lpolecenie ook na górze. Kiedy lprzyglądamy się działającej sedprzestrzeni wzorcowej, możemy lepiej zrozumieć, co dzieje się za kulisami i lepiej zrozumieć, w jaki sposób kierować jej wysiłkami.
W tym przypadku możemy obserwować seddane wejściowe stosu, dopóki nie znajdzie drugiego wystąpienia danych \n#.*\ndotanwejściowych, i kiedy zacznie drukować poprzednią linię na raz. To trochę fajne. Wiele się nauczyłem, pracując nad tym.
Bardzo ładnie, dziękuje! Ostatni akapit z objaśnieniami jest wspaniały, poświęcę również sporo czasu na naukę tego wpisu. Niezły stos!
dotancohen
1
@dotancohen - to było naprawdę dobre pytanie. Spójrz na edycję, aby zobaczyć stos .
mikeserv
2
W historii edycji zauważam wpis Handle many dotans. Jestem pewien, że to najgorszy koszmar mojej żony.
dotancohen
1
@dotancohen - tak, to było trudne. Rzeczy, jak #\ndotan\ndotantrudno jest dla tych rzeczy. Mam na myśli to, kiedy mówię to dobre pytanie. I pomyśleć Mam to po prostu idealne, ale jeden problem, który mógłby uruchomić pod jest, jeśli komentarz bloki są oddzielone 1000 linii - że będzie zwalniać. Możesz włożyć coś s/\n/&/150;tw stylu przed pierwszą /\n#rzeczą, aby wyłamać bufor, jeśli obejmuje on na przykład 150 linii. A tak w ogóle, może to tylko co ona czekali przez cały czas !
Oto kolejna
sed
:Tak, jak prosisz. Po prostu działa na stosie - buduje go, gdy jest to konieczne i tak długo, jak to konieczne między wystąpieniami komentowanych linii, i zrzuca stary bufor na korzyść nowej komentowanej linii dalej na wejściu, gdy ją znajdzie. Obrazek...
Przepraszam, nie wiem, dlaczego to zrobiłem. Ale przyszło mi do głowy.
W każdym razie
sed
rozkłada swoje bufory między każdą ostatnią komentowaną linią w dowolnej serii, nigdy nie zatrzymując ani jednego więcej w swoim buforze, niż jest to konieczne do dokładnego śledzenia ostatniego komentowanego wystąpienia, a jeśli w dowolnym momencie napotka ostatnią linię podczas tej operacji, spróbuje końcowag
instrukcja wykonania gałęzi i odgałęzieniet
szacują, że cały bufor zostanie wydrukowany, w przeciwnym razieP
zrzuci wszystkie linie, które zwolni z bufora, gdy tylko to zrobi.Wydaje mi się, że właśnie to przywodziło na myśl akordeon ...
Jest tylko jedna różnica między tym poleceniem a powyższym i jest to
l
polecenie ook na górze. Kiedyl
przyglądamy się działającejsed
przestrzeni wzorcowej, możemy lepiej zrozumieć, co dzieje się za kulisami i lepiej zrozumieć, w jaki sposób kierować jej wysiłkami.W tym przypadku możemy obserwować
sed
dane wejściowe stosu, dopóki nie znajdzie drugiego wystąpienia danych\n#.*\ndotan
wejściowych, i kiedy zacznie drukować poprzednią linię na raz. To trochę fajne. Wiele się nauczyłem, pracując nad tym.źródło
Handle many dotans
. Jestem pewien, że to najgorszy koszmar mojej żony.#\ndotan\ndotan
trudno jest dla tych rzeczy. Mam na myśli to, kiedy mówię to dobre pytanie. I pomyśleć Mam to po prostu idealne, ale jeden problem, który mógłby uruchomić pod jest, jeśli komentarz bloki są oddzielone 1000 linii - że będzie zwalniać. Możesz włożyć cośs/\n/&/150;t
w stylu przed pierwszą/\n#
rzeczą, aby wyłamać bufor, jeśli obejmuje on na przykład 150 linii. A tak w ogóle, może to tylko co ona czekali przez cały czas !