Ich hatte den Eindruck, von derPOSIX-Spezifikationen fürsed
dass es notwendig ist, den Text in der Zeile nach dem Befehl linksbündig auszurichten i\
, es sei denn, Sie möchten führende Leerzeichen in der Ausgabe.
Ein kurzer Test auf meinem Mac (mit BSD sed) zeigt, dass dies vielleicht der Fall istnichtnotwendig:
$ cat test.sed
#!/bin/sed -f
i\
This line starts with spaces.
$ echo some text | sed -f test.sed
This line starts with spaces.
some text
$
Ich kann dies jedoch nirgends dokumentiert finden. Es steht nicht in den POSIX-Spezifikationen und nicht einmal auf sed
der Manpage meines Systems.
Kann ich mich in sed
Skripten, die portierbar sein sollen, auf dieses Verhalten verlassen? Wie portabel ist es?
(Ist es dokumentiertüberall?)
(Bonusfrage: Ist es überhaupt möglich, sed
das Einfügen von Leerzeichen am Anfang einer an übergebenen festen Zeile zu erzwingen i\
?)
Antwort1
Nein, aber Ihr Skript ist portierbar, solange Sie führende Leerzeichen maskieren. Warum? Weil einige sed
s Leerzeichen aus Textzeilen entfernen und die einzige Möglichkeit, dies zu vermeiden, darin besteht, führende Leerzeichen zu maskieren, wie diese Manualpages aus dem letzten Jahrhundert erklären:1,2,3
Dasselbe gilt für BSD
sed
( OSX
habe den Code einfach kopiert, es ist nicht ihre Erweiterung) und wenn Sie die Archive überprüfen und dieman
Seite vonBSD 2.11
es ist ziemlich klar:
(1)i\
Text
.......
Ein Argument bezeichnetTextbesteht aus einer oder mehreren Zeilen, von denen alle bis auf die letzte mit enden, um'\'
den Zeilenumbruch zu verbergen. Backslashes im Text werden wie Backslashes in der Ersetzungszeichenfolge eines's'
Befehls behandelt und können verwendet werden, um anfängliche Leerzeichen und Tabulatoren vor dem Entfernen zu schützen, das in jeder Skriptzeile durchgeführt wird.
Wo ist dies nun in der POSIX-Spezifikation dokumentiert? Dort steht nur
Der Argumenttext muss aus einer oder mehreren Zeilen bestehen. Jedem eingebetteten <newline> im Text muss ein <backslash> vorangestellt werden. Andere <backslash>-Zeichen im Text müssen entfernt werden und das folgende Zeichen muss wörtlich behandelt werden.
und wenn Sie nach unten scrollen unterGRUNDLAGEes sagt
Die Anforderungen für die Akzeptanz von <blank>- und <space>-Zeichen in Befehlszeilen wurden expliziter formuliert als in früheren Vorschlägen, um die historische Praxis klar zu beschreiben und Verwirrung über den Satz „Schützen Sie anfängliche Leerzeichen und Tabulatoren vor dem Entfernen, das in jeder Skriptzeile erfolgt“ zu beseitigen, der in vielen historischen Dokumentationen der Textbeschreibung des Dienstprogramms sed vorkommt. (Es ist nicht bekannt, dass alle Implementierungen <blank>-Zeichen aus Textzeilen entfernt haben, obwohl sie alle führende <blank>-Zeichen vor der Adresse in einer Befehlszeile zugelassen haben.)
Da der Teil mit"Backslashes können verwendet werden, um"war in diesem Zitat nicht enthalten, der verbleibende Satz"Anfängliche Leerzeichen schützen..."macht keinen Sinn... 1
Zusammenfassend lässt sich sagen: Einige Implementierungen haben (und tun dies immer noch) Leerzeichen aus Textzeilen entfernt. Da jedoch die POSIX-Spezifikation, der alle Implementierungen entsprechen sollten, besagt:
Andere <Backslash>-Zeichen im Text müssen entfernt werden und das folgende Zeichen muss wörtlich behandelt werden.
Wir können daraus schließen, dass die portable Möglichkeit zum Einrücken der Zeilen im einzufügenden Text darin besteht, das führende Leerzeichen in jeder dieser Zeilen zu maskieren.
1: Ich verstehe auch nicht, warum OSX
die BSD
Leute den gesamten Absatz auf der Seite geändert haben man
, ohne den Quellcode zu verändern – das Verhalten ist dasselbe wie zuvor, aber der Man-Abschnitt, der dieses Zeug dokumentiert, ist nicht mehr da.
Antwort2
Es ist eine OSX- sed
Erweiterung, kein Standardverhalten. Sie können sehendieser Link, in Funktioncompile_text
:
/*
* Compile the text following an a or i command.
*/
static char *
compile_text()
{
int asize, size;
char *text, *p, *op, *s;
char lbuf[_POSIX2_LINE_MAX + 1];
asize = 2 * _POSIX2_LINE_MAX + 1;
text = xmalloc(asize);
size = 0;
while (cu_fgets(lbuf, sizeof(lbuf))) {
op = s = text + size;
p = lbuf;
EATSPACE();
for (; *p; p++) {
if (*p == '\\')
p++;
*s++ = *p;
}
size
Sie haben mithilfe von EATSPACE
Makros Leerzeichen gefressen.
In FreeBSD , das , , fälschlicherweise als Zeilenfortsetzungszeichen sed
behandeln kann, ist das Verhalten seltsamer. In meinem FreeBSD 9.3:\
a
i
c
$ echo 1 | sed -e 'i\ 1'
": extra characters after \ at the end of i command
Aber:
$ echo 1 | sed -e 'i\
2'
2
1
funktioniert, und es frisst auch Speicherplatz.
GNU sed
, das Erbstück, sed
hat dieses Problem nicht.
Antwort3
Cuonglmgab die beste Antwort, aber fürs Protokoll:GNU sed
tut:
echo foo | sed 'i\
This line starts with spaces.'
Ausgabe:
This line starts with spaces.
foo