
Ich versuche, eine Aliasfunktion zu erstellen, um die eingegebene Zeile aus der Datei zu entfernen:
function remove_line(){
line_to_remove="'s/^"$1"$//g'"
sed -i $(line_to_remove) my_file
}
Beispiel:
remove_line domain.com
Diese Domäne sollte aus einer bestimmten Datei entfernt werden.
Es scheint jedoch, dass es $
nicht richtig interpretiert wird. Was mache ich falsch?
Antwort1
Ihr Hauptproblem ist, dass es $(line_to_remove)
sich um eineBefehlsersetzung, d. h. ein Ausdruck, der durch den Text ersetzt wird, der vom Befehl in den Klammern ( ausgegeben wird line_to_remove
, was voraussichtlich zu einem „Befehl nicht gefunden“-Fehler führen würde). Sie möchten wahrscheinlich "$line_to_remove"
stattdessen verwenden.
Das Einfügen einer Shell-Variable in einen sed
Substitutionsausdruck ist jedoch nicht optimal, da es zu viele Bedingungen an die eingefügte Zeichenfolge stellt (es muss sich um einen gültigen regulären Ausdruck handeln und darf keine enthalten /
usw.).
Stattdessen schlage ich vor, zu verwenden grep
und das Ergebnis entweder in die Standardausgabe oder in eine temporäre Datei zu schreiben, die die Originaldatei nach erfolgreicher Ausführung von ersetzt grep
, oder Sie können sponge
die Originaldatei überschreiben lassen (aus dem GNU-moreutils-Paket).
remove_lines () {
grep -v -Fx -e "$1" my_file | sponge my_file
}
Die hier verwendeten Optionen grep
stellen sicher, dass die als erstes Argument der Funktion angegebene Zeile unverändert verwendet wird (nicht als regulärer Ausdruck), eine Zeile von Anfang bis Ende abgleicht und übereinstimmende Zeilen aus der Eingabe entfernt.
Ohne sponge
:
remove_lines () {
tmpfile=$(mktemp)
grep -v -Fx -e "$1" my_file >"$tmpfile" && mv "$tmpfile" my_file
rm -f "$tmpfile"
}
Dies mv
wird nur ausgeführt, wenn es grep
erfolgreich ausgeführt wurde. rm -f
Andernfalls wird die temporäre Datei entfernt.
Persönlich würde ich die Funktion wahrscheinlich so schreiben:
remove_lines () {
grep -v -Fx -e "$1"
}
Dies ermöglicht einem Benutzer, es folgendermaßen zu verwenden:
remove_lines "my line" <my_file | sponge my_file
some-command | remove_lines "bumble bee" | other-command
Dadurch fungiert die Funktion als Filter, derhält nur, was es verspricht, d. h., es entfernt Zeilen aus der Eingabe und kümmert sich nicht darum, woher die Eingabe kommt oder wohin sie geht.