Od jakiegoś czasu używam „sed” na Linuksie, ale miałem trochę trudności z próbą użycia go na OSX, ponieważ „POSIX sed” i „GNU sed” mają tak wiele małych różnic. Obecnie mam problem z tym, jak wstawić wiersz tekstu po określonym numerze wiersza. (w tym przypadku wiersz 4)
Na Linuksie zrobiłbym coś takiego:
sed --in-place "4 a\ mode '0755'" file.txt
Więc na OSX próbowałem tego:
sed -i "" "4 a\ mode '0755'" file.txt
Daje mi to jednak błąd „dodatkowe znaki po \ na końcu polecenia”. Jakieś pomysły, co tu jest nie tak? Czy mam literówkę? Czy też nie rozumiem innej różnicy między wersjami sed?
Odpowiedzi:
Ściśle mówiąc, specyfikacja POSIX dla
sed
wymaga nowej linii poa\
:To sprawia, że pisanie jednej wkładki trochę bólu, co jest prawdopodobnie powodem następującym rozszerzeniem GNU do
a
,i
orazc
komendy:Dlatego, aby być przenośnym ze swoją
sed
składnią, musisz wa\
jakiś sposób dołączyć nowy wiersz . Najprostszym sposobem jest po prostu wstawienie cytowanego nowego wiersza:(gdzie
$
i>
są podpowiedziami powłoki). Jeśli okaże się, że bólbash
[1] ma$' '
składnię cytowania do wstawiania znaków ucieczki w stylu C, po prostu użyj[1] i mksh (r39b +) i niektóre powłoki bourne bez bash (np. / Bin / sh w FreeBSD 9+)
źródło
Jak opisano w tej odpowiedzi , jest to przydatne, gdy używasz komend sed, takich jak
i
ia
używasz wielu-e "..."
klauzul. Każdą z tych klauzul należy rozumieć jako oddzieloną znakami nowej linii. W przeciwnym razie poleceniai
ia
są trudne do użycia w wbudowanych skryptach sed (są zaprojektowane do użycia w wielowierszowym pliku skryptu sed wywoływanym przy użyciused -f file ...
). Wygląda na to, że nie można użyć niejawnej nowej linii wprowadzonej na końcu-e
klauzuli, aby oddzielića\
i wiersz tekstu, który należy dołączyć. Ale możesz go użyć do zakończenia wiersza tekstu, który chcesz dołączyć.W tym konkretnym przypadku to, co próbujesz zrobić, może zostać osiągnięte za pomocą jednej
-e ...
klauzuli. Musisz tylkoa
poprawnie użyć polecenia. Zgodnie ze standardem POSIX, po nima
musi następować a\
, następnie musi następować nowa linia, następnie zostanie wstawiona reszta następnego linii (aż-e
napotka się nową linię lub koniec klauzuli). Więc możesz zrobić:źródło
Wydaje się, że GNU sed jest znacznie częściej używany niż sed POSIX, na podstawie przykładów / samouczków, których i tak użyłem.
Przekonałem się, że dużo łatwiej jest po prostu zainstalować GNU sed na dowolnym komputerze OSX, którego używam. Jeśli jesteś zainteresowany, najlepszym sposobem na to jest zainstalowanie go przez Homebrew .
Możesz albo po prostu
$ brew install gnu-sed
uzyskać wszystkie popularne narzędzia GNU$ brew install coreutils
.Następnie, gdy napotkasz problem ze składnią w programie
date
lub innym programie, możesz po prostu użyć wersji GNU. W końcu zdecydowałem, że łatwiej jest zawsze używać wersji GNU i umieścić je wcześniej niż wersje systemowe w moimPATH
.źródło
Perl nie cierpi na takie zależne od platformy GNU vs. non-GNU vs. „zastrzeżone” osobliwości. Mógłbyś:
-n' option creates a loop that reads every line of the input file. Unlike its cousin
-P(not used here) it doesn't automatically print every line read. The
-iinvokes in-place replacement. The argument to
-i(viz. ".old") can be dropped or changed. It leaves a backup of the unmodified file. The -e
sygnalizuje początek skryptu.$.
Oznacza line-numer, zaczynając od linii-1. W ten sposób wiersz poleceń odczytuje „plik”, a gdy numer wiersza jest równy 4, wypisuje ten wiersz, a następnie cokolwiek chcesz wstrzyknąć.Chciałbym dodać, że Perl zawdzięcza swoje korzenie
sed
AWK i C, więc składnia prostych podstawień itp. Nie jest bardzo stromą krzywą uczenia się.źródło
perl -wlpi.old -e 'print "mode 0755" if $. == 5' file.txt
.-p
Przełącznik działa dobrze tutaj (ponieważ chcemy wydrukować każdą linię); musimy tylko zmienić logikę z „drukowanie po linii 4” na „drukowanie przed linią 5”. A-l
przełącznik czyni go tak, że „\ n” jest drukowany automatycznie z każdymprint
, więc nie trzeba go wydrukować samodzielnie.