Chciałbym edytować plik w miejscu, dodając wiersz, tylko jeśli jeszcze nie istnieje, aby mój skrypt był kuloodporny.
Normalnie zrobiłbym coś takiego:
cat >> ~/.bashrc <<EOF
export PATH=~/.composer/vendor/bin:\$PATH
EOF
Można to również zrobić za pomocą ansible ( line
+ insertafter=EOF
+ regexp
), ale to inna historia.
W vi / ex mogłem zrobić coś takiego:
ex +'$s@$@\rexport PATH=\~/.composer/vendor/bin:$PATH@' -cwq ~/.bashrc
ale jak mogę sprawdzić, czy linia już tam jest (a więc nic nie robić) idealnie bez powtarzania tej samej linii?
A może istnieje prostszy sposób na zrobienie tego w edytorze Ex?
substitute
ex-command
kenorb
źródło
źródło
grep -Fq 'export PATH=~/.composer/vendor/bin:$PATH' ~/.bashrc || ex ...
(lubcat
, jeśli o to chodzi)?ex ~/.bashrc -c "if search('export PATH=\~\/.composer\/vendor\/bin:\$PATH')>0 | norm quit | endif | norm Aexport PATH=~/.composer/vendor/bin:$PATH"
export
jest to polecenie , więc reszta wiersza jest słowem powłoki, a NIE przypisaniem. Dlatego, inaczej niż w przypadku przypisania zmiennej (która nie korzystaexport
), potrzebujesz podwójnych cudzysłowów, w przeciwnym razie spowoduje to przerwanie białych znaków . Zobacz także Jak poprawnie dodać ścieżkę do ŚCIEŻKI .Odpowiedzi:
Jeśli chcesz kuloodporny , prawdopodobnie potrzebujesz czegoś bardziej przenośnego niż skomplikowane opcje powyżej. Chciałbym trzymać się funkcji POSIX
ex
i uczynić to głupio prostym: po prostu usuń linię, jeśli tam jest (niezależnie od tego, ile razy tam jest), dodaj ją na końcu pliku, a następnie zapisz i wyjdź:Zakotwicziłem regex dla dodatkowej solidności, chociaż myślę, że prawie niemożliwe jest przypadkowe dopasowanie tego regexu. (Zakotwiczone za pomocą środków
^
i$
tak regex będzie tylko dopasować jeśli odpowiada on całą linię).Zauważ, że
+cmd
składnia nie jest wymagane przez POSIX, ani wspólna cecha pozwala wielu-c
argumentów.Można to zrobić na wiele innych prostych sposobów. Na przykład dodaj wiersz na końcu pliku, a następnie uruchom dwa ostatnie wiersze pliku przez zewnętrzny filtr UNIX
uniq
:Jest to bardzo czyste i proste, a także w pełni zgodne z POSIX. Wykorzystuje funkcję Escape
ex
dla zewnętrznego filtrowania tekstu oraz narzędzie powłoki określone przez POSIXuniq
Najważniejsze jest to, że
ex
jest przeznaczony do edycji plików w miejscu i jest zdecydowanie najbardziej przenośnym sposobem na osiągnięcie tego w sposób nieinteraktywny. To wyprzedza nawet oryginalnevi
, faktycznie, nazwavi
jest „wizualnego edytora”, a redaktor non-wideo został zbudowany na toex
).Aby jeszcze bardziej uprościć (i zredukować go do jednej linii), użyj
printf
polecenia wysyłania poleceń doex
:źródło
Możliwym rozwiązaniem jest utworzenie funkcji, aby to zrobić:
Najpierw tworzymy zmienną lokalną,
l:res
która będzie używana do zliczania liczby wystąpień linii.Używamy
global
polecenia: za każdym razem, gdy linia jest dopasowywana,l:res
jest zwiększana.Na koniec, jeśli
l:res
nadal wynosi 0, oznacza to, że linia nie pojawia się w pliku, dzięki czemu przechodzimy do ostatniej liniiG
i tworzymy nową linię,o
na której piszemy linię do dodania.Uwaga 1 Metoda, której użyłem do ustawienia wartości,
l:res
jest nieco ciężka i można ją zastąpić metodą sugerowaną przez @Alex w odpowiedzi na coś takiego:Uwaga 2 Aby uelastycznić funkcję, możesz użyć argumentów:
escape()
dodaniu\
przed znakami znaku, który może powodować problemy podczas wyszukiwania.Pamiętaj również, że nadal będziesz musiał sam uciec
\
podczas wywoływania funkcji (nie udało mi się uciec\
automatycznie):źródło
Próbować:
Zauważ, że
:append
nie będzie działać wewnątrzif endif
-bloku w trybie Ex (patrz VimDoc ), więc muszęnorm A...
wyjść na zewnątrz.źródło
Zwykle używam:
źródło
Aby uprościć i uniknąć obecności wielu
\
, dodawana będzie liniaexport PATH=mybin:PATH
.Główna strategia:
mybin
zastąp tekst „nie- ” (cały plik) tekstem + definicja ścieżki mybin:lub z większym wcięciem dydaktycznym :
Jeśli mamy dopasowanie:
&
ma pełny tekstbashrc
i&
nie zawiera/mybin:/
więc:
AKTUALIZACJA : Wreszcie możemy stworzyć skrypt vim:
chmod 755 i zainstaluj go. Stosowanie:
bashrcfix
bądź ostrożny: w
\v
trybie=
oznacza opcjonalneźródło
Większość z tych odpowiedzi wydaje się skomplikowana, co powiesz na dobre stare polecenia powłoki:
Może to być z łatwością funkcja Bash:
EDYCJA : Kod wyjścia grep jest ważny iw tym przypadku należy go odwrócić
! grep
;grep -v
nie wyjdzie zgodnie z oczekiwaniami w tej sytuacji. Dziękuję @joeytwiddle za wskazówkę.źródło
grep -v
daje ci kod wyjścia, który chcesz. Ale! grep
powinienem to zrobić.-v
tego!
.-F
, abygrep
nie interpretować znaków jako wyrażeń regularnych, i 2. Używać-q
zamiast przekierowywać na/dev/null
. Zobacz mój wcześniejszy komentarz do pytania .-q
i jakie-F
opcje? Myślałem, że>/dev/null
jest bardziej uniwersalny na różnych platformach (słońce vs hp vs Mac OS X vs Ubuntu vs FreeBSD vs…)