Ich möchte eine Datei direkt durch Anhängen einer Zeile bearbeiten, nur wenn sie noch nicht vorhanden ist, um mein Skript kugelsicher zu machen.
Normalerweise würde ich so etwas machen wie:
cat >> ~/.bashrc <<EOF
export PATH=~/.composer/vendor/bin:\$PATH
EOF
Es ist auch möglich, dies über ansible ( line
+ insertafter=EOF
+ regexp
) zu tun , aber es ist eine andere Geschichte.
In vi / ex könnte ich so etwas machen wie:
ex +'$s@$@\rexport PATH=\~/.composer/vendor/bin:$PATH@' -cwq ~/.bashrc
aber wie überprüfe ich dann im Idealfall, ob die Leitung bereits vorhanden ist (und tue somit nichts), ohne dieselbe Zeile zu wiederholen?
Oder gibt es eine einfachere Möglichkeit, dies im Ex-Editor zu tun?
substitute
ex-command
Kenorb
quelle
quelle
grep -Fq 'export PATH=~/.composer/vendor/bin:$PATH' ~/.bashrc || ex ...
(oder auchcat
)?ex ~/.bashrc -c "if search('export PATH=\~\/.composer\/vendor\/bin:\$PATH')>0 | norm quit | endif | norm Aexport PATH=~/.composer/vendor/bin:$PATH"
export
ein Befehl ist. Der Rest der Zeile ist also ein Shell-Wort, keine Zuweisung. Daher benötigen Sie im Gegensatz zu einer Variablenzuweisung (die nicht verwendet wirdexport
) doppelte Anführungszeichen, da diese sonst im Leerzeichen unterbrochen wird . Siehe auch So fügen Sie PATH einen Pfad korrekt hinzu .Antworten:
Wenn Sie kugelsicher sein möchten , möchten Sie wahrscheinlich etwas, das etwas tragbarer ist als die oben genannten komplizierten Optionen. Ich würde mich an die POSIX-Funktionen von halten
ex
und es einfach machen: Entfernen Sie einfach die Zeile, wenn sie vorhanden ist (unabhängig davon, wie oft sie vorhanden ist), fügen Sie sie am Ende der Datei hinzu, speichern Sie sie und beenden Sie sie:Ich verankert die Regex für zusätzliche Robustheit, obwohl ich denke , dass es fast unmöglich ist, aus Versehen diese Regex. (Verankert bedeutet Verwenden
^
und$
daher stimmt der reguläre Ausdruck nur überein, wenn er mit einer ganzen Zeile übereinstimmt .)Beachten Sie, dass die
+cmd
Syntax weder von POSIX benötigt wird noch das gemeinsame Merkmal, mehrere-c
Argumente zuzulassen .Es gibt eine Vielzahl anderer einfacher Möglichkeiten, dies zu tun. Fügen Sie beispielsweise die Zeile am Ende der Datei hinzu und führen Sie die letzten beiden Zeilen der Datei über den externen UNIX-Filter aus
uniq
:Dies ist sehr, sehr sauber und einfach und auch vollständig POSIX-konform. Es verwendet die Escape-Funktion von
ex
für die externe Textfilterung und das von POSIX angegebene Shell-Dienstprogrammuniq
Unterm Strich ist,
ex
ist entworfen für in-Place - Datei bearbeiten , und es ist bei weitem die meisten tragbare Art und Weise zu erreichen , dass in einer nicht-interaktiven Art und Weise. Es ist sogar älter als das Originalvi
- der Namevi
steht für "Visual Editor" und der nicht-visuelle Editor, auf dem es aufgebaut wurde, warex
.)Verwenden Sie zur noch größeren Vereinfachung (und um es auf eine einzelne Zeile zu reduzieren)
printf
die Befehle anex
:quelle
Eine mögliche Lösung besteht darin, eine Funktion zu erstellen, um dies zu tun:
Zuerst erstellen wir eine lokale Variable, mit
l:res
der die Anzahl der Vorkommen der Zeile gezählt wird.Wir verwenden den
global
Befehl: Jedes Mal, wenn die Zeile übereinstimmt,l:res
wird sie erhöht.Wenn schließlich
l:res
noch 0 ist, bedeutet dies, dass die Zeile nicht in der Datei angezeigt wird, sodass wir dank zur letzten Zeile wechselnG
und eine neue Zeile erstellen, mito
der wir die hinzuzufügende Zeile schreiben.Anmerkung 1 Die Methode, mit der ich den Wert von festgelegt habe,
l:res
ist etwas schwer und kann durch die von @Alex in seiner Antwort vorgeschlagene ersetzt werden :Hinweis 2 Um die Funktion flexibler zu gestalten, können Sie folgende Argumente verwenden:
escape()
dem Hinzufügen eines\
vor den Zeichen, was zu Problemen bei der Suche führen kann.Beachten Sie auch, dass Sie
\
beim Aufrufen der Funktion immer noch selbst entkommen müssen (ich habe es nicht geschafft,\
automatisch zu entkommen ):quelle
Versuchen:
Beachten Sie, dass der Innenblock im Ex-Modus
:append
nicht funktioniertif endif
(siehe VimDoc ), daher muss ich ihn nachnorm A...
außen stellen.quelle
Ich benutze normalerweise:
quelle
Um die Anwesenheit vieler zu vereinfachen und zu vermeiden
\
, wird die hinzuzufügende Zeile verwendetexport PATH=mybin:PATH
.Hauptstrategie: Ersetzen Sie den "Nicht-
mybin
" Text (alle Dateien) durch Text + Mybin-Pfad-Definition:oder mit mehr didaktischer Einrückung :
Wenn wir ein Match haben:
&
hat den vollständigen Text vonbashrc
und&
beinhaltet nicht/mybin:/
damit:
UPDATE : Endlich können wir ein Vim-Skript erstellen:
chmod 755 und installiere es. Verwendungszweck:
bashrcfix
Vorsicht: Im
\v
Modus=
bedeutet optionalquelle
Die meisten dieser Antworten scheinen kompliziert zu sein, wie wäre es mit guten alten Shell-Befehlen:
Dies könnte leicht eine Bash-Funktion sein:
BEARBEITEN : Der Exit-Code von grep ist wichtig und muss in diesem Fall umgekehrt verwendet werden
! grep
.grep -v
wird in dieser Situation nicht wie erwartet beendet. Danke @joeytwiddle für den Tipp.quelle
grep -v
Sie den gewünschten Exit-Code erhalten. Sollte! grep
es aber tun.-v
nur das!
.-F
damitgrep
Zeichen nicht als reguläre Ausdrücke interpretiert werden, und 2. Verwenden Sie,-q
anstatt umzuleiten/dev/null
. Siehe meinen früheren Kommentar zur Frage .-q
und welche-F
Optionen? Ich dachte, das wäre>/dev/null
universeller unter verschiedenen Plattformen (Sonne gegen HP gegen Mac OS X gegen Ubuntu gegen FreeBSD gegen ...)