Ich benutze 'sed' schon eine Weile unter Linux, hatte aber einige Schwierigkeiten, es unter OSX zu benutzen, da 'POSIX sed' und 'GNU sed' so viele kleine Unterschiede haben. Derzeit habe ich Probleme damit, nach einer bestimmten Zeilennummer eine Textzeile einzufügen. (in diesem Fall Zeile 4)
Unter Linux würde ich so etwas machen:
sed --in-place "4 a\ mode '0755'" file.txt
Also habe ich es unter OSX versucht:
sed -i "" "4 a\ mode '0755'" file.txt
Dadurch erhalte ich jedoch den Fehler "Zusätzliche Zeichen nach \ am Ende eines Befehls". Irgendwelche Ideen, was hier falsch ist? Habe ich einen Tippfehler? Oder verstehe ich keinen weiteren Unterschied zwischen sed-Versionen?
Antworten:
Genau genommen erfordert die POSIX-Spezifikation für
sed
eine neue Zeile nacha\
:Dies macht Einzeiler ein wenig Schmerzen zu schreiben, die für die folgenden wahrscheinlich der Grund ist GNU - Erweiterung auf die
a
,i
undc
Befehle:sed
Um also mit Ihrer Syntax portabel zu sein , müssen Sie nach dema\
irgendwie eine neue Zeile einfügen . Am einfachsten fügen Sie einfach eine zitierte Zeile ein:(wo
$
und>
sind Shell-Eingabeaufforderungen). Wenn Sie feststellen, dass ein Schmerz auftritt, hatbash
[1] die$' '
Anführungssyntax zum Einfügen von Escape-Zeichen im C-Stil. Verwenden Sie also einfach[1] und mksh (r39b +) und einige Nicht-Bash-Bourne-Shells (zB / bin / sh in FreeBSD 9+)
quelle
Wie in dieser Antwort beschrieben , ist es hilfreich, wenn Sie sed-Befehle wie
i
und verwendena
, um mehrere-e "..."
Klauseln zu verwenden. Jede dieser Klauseln wird als durch Zeilenumbrüche getrennt verstanden. Die Befehlei
unda
sind in Inline-Sed-Skripten nur schwer zu verwenden (sie sind für die Verwendung in einer mehrzeiligen Sed-Skriptdatei vorgesehen, die mit aufgerufen wirdsed -f file ...
). Es sieht so aus, als könnten Sie die implizite neue Zeile, die am Ende einer-e
Klausel eingefügt wird, nicht verwenden, um die anzufügende Textzeile von der anzuhängenden Textzeile zu trennena\
. Sie können es jedoch verwenden, um die anzufügende Textzeile zu beenden.In diesem speziellen Fall kann das, was Sie versuchen, mit einer einzigen
-e ...
Klausel erreicht werden. Sie müssen dena
Befehl nur richtig verwenden. Nach dem POSIX-Standarda
muss nach a\
eine neue Zeile eingefügt werden, danach wird der Rest der nächsten Zeile eingefügt (bis eine neue Zeile oder das Ende der-e
Klausel angetroffen wird). Sie könnten also Folgendes tun:quelle
GNU sed wird anscheinend viel häufiger verwendet als POSIX sed, basierend auf Beispielen / Tutorials, die ich sowieso verwendet habe.
Ich habe festgestellt, dass es viel einfacher ist, GNU sed auf jedem OSX-Rechner zu installieren, den ich verwende. Wenn Sie interessiert sind, installieren Sie es am besten über Homebrew .
Sie können entweder nur
$ brew install gnu-sed
oder alle gängigen GNU-Dienstprogramme mit$ brew install coreutils
.Wenn Sie dann auf ein Syntaxproblem mit
date
einem anderen Programm stoßen, können Sie einfach die GNU-Version verwenden. Irgendwann habe ich einfach festgestellt, dass es einfacher ist, die GNU-Versionen immer zu verwenden und sie früher als die Systemversionen in meine zu stellenPATH
.quelle
Perl leidet nicht unter solchen plattformabhängigen Unterschieden zwischen GNU und Nicht-GNU und unter "proprietären" Eigenheiten. Du könntest es tun:
Das
-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
signalisiert den Beginn des Skripts.Das
$.
kennzeichnet die Zeilennummer, beginnend mit Zeile-1. Die Befehlszeile lautet also 'file' und wenn die Zeilennummer gleich 4 ist, wird diese Zeile gedruckt, gefolgt von dem, was Sie einfügen möchten.Ich würde gerne hinzufügen, dass Perl seine Wurzeln
sed
AWK und C verdankt , sodass die Syntax für einfache Substitutionen usw. keine sehr steile Lernkurve darstellt.quelle
perl -wlpi.old -e 'print "mode 0755" if $. == 5' file.txt
. Der-p
Schalter funktioniert hier gut (da wir jede Zeile drucken wollen); Wir müssen nur die Logik von "Drucken nach Zeile 4" auf "Drucken vor Zeile 5" ändern . Und der-l
Schalter bewirkt, dass "\ n" automatisch mit jedem gedruckt wirdprint
, sodass Sie es nicht selbst drucken müssen.