sed verhält sich unter FreeBSD und Linux anders?

12

Ich benutze sowohl Linux als auch FreeBSD (insbesondere Debian Linux und PC-BSD) und fand etwas Seltsames sed.

Ich muss häufig Dateien mit "durch Tabulatoren getrennten Werten" in "durch Kommas getrennte Werte" konvertieren. Die einfachste Methode, die ich kenne, ist die folgende sed:

sed 's/\t/,/g' inputFile.txt > outputFile.csv

Dies funktioniert perfekt unter Linux: Es ersetzt jeden Tabulator mit einem Komma ... aber unter FreeBSD ersetzt es nichts !!!

Vermisse ich etwas? Gibt es bei FreeBSD sedeine andere Syntax als bei Linux?

Barranka
quelle

Antworten:

9

Vielleicht sollten Sie die -EOption (oder -rwie im Handbuch erklärt ) verwenden, um die Kompatibilität mit GNU Sed zu gewährleisten. In Ihrem Fall können Sie Gnu Sed installieren, wenn Sie es gewohnt sind (Portierung unter FreeBSD), oder es wird lange dauern, Skripte zu portieren.

Und merke dir. Wenn ein BSD-Befehl nicht wie die Gnu-Version dieses Dienstprogramms funktioniert, heißt das nicht, dass es kaputt ist;)


quelle
1
Vielen Dank. Die -EOption macht den Trick (sowohl unter FreeBSD als auch unter Mac OS X).
Barranka
Auf meinem FreeBSD 9 hilft die Option -E nicht.
Ark-Kun
6

Ja, es gibt verschiedene Unterschiede, das Verhalten-i , das einzige zu sein, von dem ich etwas weiß.

Ich habe noch nie BSD verwendet, daher kann ich nicht wirklich mit den Details helfen, aber es könnte eine Problemumgehung sein, trstattdessen Folgendes zu verwenden :

tr '\t' , < inputFile.txt > outputFile.csv

Ein angenehmer Nebeneffekt ist, trdass deutlich schneller sein sollte. Ich habe das auf meinem Linux mit einer Testdatei mit 50000 Zeilen getestet, von denen jede 2 Registerkarten hatte:

$ time tr '\t' , < foo.txt > /dev/null 

real    0m0.004s
user    0m0.000s
sys     0m0.000s

$ time sed 's/\t/,/g' foo.txt > /dev/null 

real    0m0.039s
user    0m0.036s
sys     0m0.000s
terdon
quelle
tr '\t' ,ist tragbarer als tr $'\t' ,. tr '[\t]' '[,]'wäre sogar portabel auf einige alte SysV-Systeme.
Stéphane Chazelas
tab ist das Standardtrennzeichen für cut. Die POSIX-Spezifikation für trist da . Ich habe mich geirrt, was das [alte SysV betrifft. Wie die POSIX-Spezifikation hervorhebt, [wird dies nur für Bereiche dort benötigt.
Stéphane Chazelas
@StephaneChazelas so ist es, sorry nicht sicher, womit ich es dann verwechsle. Danke auf jeden Fall für die Klarstellung.
terdon
4

Ja, im Gegensatz zu GNU interpretiert sedFreeBSD sedkeine ANSI C-Escape-Sequenzen wie \tin regulären Ausdrücken.

Eine Möglichkeit, in diesem Fall einen am wenigsten verbreiteten Nenner zu erhalten, ist die Verwendung von printf.

tab="$(printf '\t')"
printf '\t\n' | sed 's/'"${tab}"'/,/g'
printf '\t\n' | sed 's/'"$(printf '\t')"'/,/g'

Das Verhalten sed -ifür direkte Dateiänderungen kann kompatibel gemacht werden, wenn ein Schalter oder eine Option unmittelbar auf den -iSchalter folgt , z. B. sed -i -e 's/x/X/g' filesowohl für GNU sedals auch für FreeBSD sed.

Neuere Versionen von FreeBSD sed(FreeBSD 8.1 oder neuer) haben den -rSchalter, um die Kompatibilität mit GNU zu erhöhen sed.

(Darüber hinaus ist die Verwendung von POSIX-Zeichenklassen in sedregulären Ausdrücken eine gute Möglichkeit, um die Kompatibilität sicherzustellen.)

Für eine alternative, POSIX-konforme sedImplementierung siehe: Minimiert - eine kleinere, billigere, schnellere SED-Implementierung .

kroy
quelle
3

Sie sollten TABstatt der \tfolgenden Zeichen ein Literal verwenden :

sed 's/    /,/g' inputFile.txt > outputFile.csv

Siehe diesen Kommentar von Stephane zu einer anderen Frage.

Der folgende Artikel könnte Sie auch interessieren:

Ich zitiere den relevanten Teil:

Regex-Unterschiede Die

Syntax für reguläre Ausdrücke unterscheidet sich geringfügig zwischen den verschiedenen Versionen von SED. Bei den meisten Unterschieden handelt es sich um spezielle Escape-Muster, die für nicht druckbare Zeichen verwendet werden, z. B. die ASCI-Glocke und Formularvorschübe.

Joseph R.
quelle
0

Nach dem Einloggen sehe ich die nächste Ansage und speichere sie. Hoffe, es wird auch für andere nützlich sein

Möchten Sie sed (1) verwenden, um eine Datei an Ort und Stelle zu bearbeiten? Nun, um jedes 'e' in einer Datei mit dem Namen 'foo' durch ein 'o' zu ersetzen, können Sie Folgendes tun:

sed -i.bak s/e/o/g foo

Sie erhalten eine Sicherungskopie des Originals in einer Datei mit dem Namen "foo.bak". Wenn Sie jedoch keine Sicherungskopie wünschen, gehen Sie wie folgt vor:

sed -i '' s/e/o/g foo
TradeNarK
quelle
die -iOption wurde bereits abgedeckt , obwohl
Jeff Schaller