Variable in Aliasfunktion richtig ersetzen

Variable in Aliasfunktion richtig ersetzen

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.comDiese 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 sedSubstitutionsausdruck 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 grepund 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 spongedie Originaldatei überschreiben lassen (aus dem GNU-moreutils-Paket).

remove_lines () {
       grep -v -Fx -e "$1" my_file | sponge my_file
}

Die hier verwendeten Optionen grepstellen 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 mvwird nur ausgeführt, wenn es greperfolgreich ausgeführt wurde. rm -fAndernfalls 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.

verwandte Informationen