Z jakiegoś powodu nie mogę znaleźć prostej odpowiedzi na to pytanie i jestem w tej chwili trochę chwiejny. Jak mógłbym wstawić wiersz wyboru tekstu po pierwszym wierszu pasującym do określonego ciągu za pomocą sed
polecenia. Mam ...
CLIENTSCRIPT="foo"
CLIENTFILE="bar"
Chcę wstawić linię po CLIENTSCRIPT=
linii, co spowoduje ...
CLIENTSCRIPT="foo"
CLIENTSCRIPT2="hello"
CLIENTFILE="bar"
sed
. To nie jest standardowased
składnia i nie będzie działać z żadną innąsed
implementacją.Zwróć uwagę na standardową
sed
składnię (jak w POSIX, więc obsługiwaną przez wszystkie zgodnesed
implementacje wokół (GNU, OS / X, BSD, Solaris ...)):Lub w jednym wierszu:
(
-e
xpressions (i zawartość-f
plików) są łączone z nowymi wierszami, aby uzupełnićsed
interpretacje skryptu sed ).-i
Opcja edycji w miejscu jest również rozszerzenie GNU, niektóre inne implementacje (np FreeBSD) poparcie-i ''
dla tego.Możesz też
perl
zamiast tego użyć przenośności :Lub możesz użyć
ed
lubex
:źródło
sed -e '/CLIENTSCRIPT=/a\' -e 'CLIENTSCRIPT2="hello"' file
ucieka cytatowi na końcu pierwszego parametru i przerywa polecenie.csh
lubrc
rodziny,'...'
to mocne cytaty, w których ukośnik odwrotny nie jest wyjątkowy. Jedyny znany mi wyjątek tofish
powłoka.sed
nie jest tutaj zgodny z POSIX. To sprawia, że moje stwierdzenie, że jest przenośne, jest niepoprawne (dla wariantu z jedną linią). Poproszę grupę otwartą o potwierdzenie, czy rzeczywiście jest to niezgodność lub błędna interpretacja normy z mojej strony.Zgodny z POSIX za pomocą
s
polecenia:źródło
sed -e '/.../s/$/\' -e 'CLI.../'
które pozwoliłyby uniknąć problemów z wierszami zawierającymi sekwencje bajtów, które nie tworzą prawidłowych znaków.Komenda Sed, która działa zarówno na MacOS (przynajmniej OS 10), jak i na Uniksie (tzn. Nie wymaga gnu sed jak Gilles (obecnie akceptowany)):
Działa to w bashu i być może także w innych powłokach, które znają styl cytowania oceny $ '\ n'. Wszystko może znajdować się w jednej linii i działać w starszych komendach / POSIX sed. Jeśli może być wiele wierszy pasujących do CLIENTSCRIPT = "foo" (lub odpowiednik) i chcesz dodać dodatkowy wiersz tylko za pierwszym razem, możesz go przerobić w następujący sposób:
(tworzy to pętlę po kodzie wstawiania wiersza, który po prostu przewija resztę pliku, nigdy nie wracając do pierwszej komendy sed).
Możesz zauważyć, że dodałem „^ *” do pasującego wzorca, na wypadek gdyby linia ta pojawiła się w komentarzu, powiedzmy lub była wcięta. Nie jest w 100% idealny, ale obejmuje niektóre inne sytuacje, które mogą być powszechne. Dostosuj zgodnie z wymaganiami ...
Te dwa rozwiązania również rozwiązują problem (ogólne rozwiązanie dodawania linii), że jeśli twoja nowa wstawiona linia zawiera nieokreślone ukośniki odwrotne lub znaki ampersand, zostaną one zinterpretowane przez sed i prawdopodobnie nie wyjdą tak samo, jak
\n
jest np.\0
byłaby dopasowana pierwsza linia. Szczególnie przydatny, jeśli dodajesz wiersz pochodzący ze zmiennej, w którym inaczej musiałbyś uciec od wszystkiego, używając $ {var //} wcześniej, lub innej instrukcji sed itp.To rozwiązanie jest nieco mniej nieporządne w skryptach (że cytowanie i \ n nie jest łatwe do odczytania), gdy nie chcesz umieszczać tekstu zastępczego polecenia na początku wiersza, jeśli powiedzmy, w funkcji z wcięciami. Skorzystałem z tego, że $ '\ n' jest oceniany przez powłokę do nowego wiersza, nie jest to zwykła wartość \ n "pojedynczego cudzysłowu.
Robi się wystarczająco długo, więc myślę, że perl / nawet awk może wygrać z powodu większej czytelności.
źródło
s/CLIENTSCRIPT="foo"/&\
[Enter]CLIENTSCRIPT2="hello"/
. Odwrotny ukośnik musi być ostatnim znakiem w linii (bez spacji po nim), w przeciwieństwie do tego, jak to wygląda w tym komentarzu.s///
, a także wa
ii
poleceniach można „uciec”, stosując tę samą metodę, którą opisałem w moim komentarzu powyżej.Może trochę za późno, aby opublikować odpowiedź na to pytanie, ale niektóre z powyższych rozwiązań uznałem za nieco kłopotliwe.
Próbowałem prostej zamiany sznurka w sed i zadziałało:
IZnak odzwierciedla dopasowany ciąg, a następnie dodajesz \ n i nowy wiersz.
Jak wspomniano, jeśli chcesz to zrobić w miejscu:
Inna rzecz. Możesz dopasować za pomocą wyrażenia:
Mam nadzieję, że to komuś pomoże
źródło
\n
w zastępującym ciągu. Zwykły waniliowy (POSIX)sed
ma nie rozumieć\n
w ciągu zastępowania jednak, więc to nie będzie działać na BSD lub MacOS-chyba że masz zainstalowanych GNU sed jakoś. Z wanilii sed ty może osadzić nowe linie o „ucieczce” je, to znaczy, kończący linię z odwrotnym ukośnikiem, a następnie naciskając [Enter] ( odniesienie , w rubryce o[2addr]s/BRE/replacement/flags
). Oznacza to, że twoje polecenie sed musi obejmować wiele linii w terminalu.Wariant awk:
źródło
1;
, zobacz Dlaczego „1” w awk drukuje bieżącą linię?Miałem podobne zadanie i nie byłem w stanie uruchomić powyższego rozwiązania perla do pracy.
Oto moje rozwiązanie:
perl -i -pe "BEGIN{undef $/;} s/^\[mysqld\]$/[mysqld]\n\ncollation-server = utf8_unicode_ci\n/sgm" /etc/mysql/my.cnf
Wyjaśnienie:
Używa wyrażenia regularnego do wyszukiwania linii w moim pliku /etc/mysql/my.cnf, który zawierał tylko
[mysqld]
i zastąpił go[mysqld] collation-server = utf8_unicode_ci
skutecznie dodając
collation-server = utf8_unicode_ci
wiersz po wierszu zawierającym[mysqld]
.źródło
Ostatnio musiałem to zrobić zarówno dla systemów Mac, jak i Linux. Po przejrzeniu wielu postów i wypróbowaniu wielu rzeczy, moim zdaniem nigdy nie dotarłem do miejsca, w którym chciałem: wystarczająco prostego, aby zrozumieć rozwiązanie przy użyciu dobrze znanego oraz standardowe polecenia z prostymi wzorami, jedną wkładką, przenośne, z możliwością rozbudowy, aby dodać więcej ograniczeń. Potem spróbowałem spojrzeć na to z innej perspektywy, wtedy zdałem sobie sprawę, że mogę obejść się bez opcji „one-liner”, jeśli „2-liner” spełni resztę moich kryteriów. Na koniec wymyśliłem to rozwiązanie, które podoba mi się, że działa zarówno na Ubuntu, jak i na Macu, które chciałem udostępnić wszystkim:
W pierwszym poleceniu grep szuka numerów linii zawierających „foo”, cut / head wybiera 1. wystąpienie, a operacje arytmetyczne zwiększają numer pierwszego wystąpienia o 1, ponieważ chcę wstawić po wystąpieniu. W drugim poleceniu jest to lokalna edycja pliku „i” do wstawienia: ansi-c cytujący nowy wiersz, „bar”, a następnie kolejny nowy wiersz. Rezultatem jest dodanie nowej linii zawierającej „pasek” po linii „foo”. Każde z tych 2 poleceń można rozszerzyć do bardziej złożonych operacji i dopasowywania.
źródło