129 Stimmen

Warum erkennt sed nicht die \t als Registerkarte?

sed "s/\(.*\)/\t\1/" $filename > $sedTmpFile && mv $sedTmpFile $filename

Ich erwarte dies sed Skript zum Einfügen einer tab vor jeder Zeile in $filename ist es jedoch nicht. Aus irgendeinem Grund fügt es eine t stattdessen.

2 Stimmen

Da sed von Plattform zu Plattform unterschiedlich sein kann (insbesondere BSD/MacOSX gegenüber Linux), kann es hilfreich sein, die Plattform anzugeben, auf der Sie sed verwenden.

0 Stimmen

Sed "s/(.*)/# \1 /" $Dateiname | tr '#' ' \t ' > $sedTmpFile && mv $sedTmpFile $filename.

0 Stimmen

Für OS X (macOS) Benutzer, siehe diese Frage .

154voto

Mark Byers Punkte 761508

Nicht alle Versionen von sed verstehen. \t . Fügen Sie stattdessen einfach einen wörtlichen Tabulator ein (drücken Sie Ctrl - V puis Tab ).

3 Stimmen

Ah ja; zur Klarstellung: nicht alle Versionen von sed verstehen \t im Ersetzungsteil des Ausdrucks (er erkennt \t im Teil für den Mustervergleich)

3 Stimmen

Awwwwwwwwwwwwwwwwwwwwwwwww, das ist ziemlich interessant. Und seltsam. Warum wird es an einer Stelle erkannt, an der anderen aber nicht...?

3 Stimmen

Von einem Skript aus aufgerufen, wird das nicht funktionieren: Tabs würden von sh ignoriert werden. Der folgende Code aus einem Shell-Skript fügt zum Beispiel $TEXT_TO_ADD hinzu, ohne ihm eine Tabulierung voranzustellen: sed "${LINE}a \\ $TEXT_TO_ADD " $FILE .

49voto

sedit Punkte 469

Mit der Bash können Sie ein TAB-Zeichen programmatisch wie folgt einfügen:

TAB=$'\t' 
echo 'line' | sed "s/.*/${TAB}&/g" 
echo 'line' | sed 's/.*/'"${TAB}"'&/g'   # use of Bash string concatenation

1 Stimmen

Sie waren auf der richtigen Spur mit dem $'string' aber es fehlen Erklärungen. In der Tat vermute ich, dass Sie aufgrund der extrem umständlichen Verwendung wahrscheinlich ein unvollständiges Verständnis haben (wie die meisten von uns mit bash). Siehe meine Erklärung unten: stackoverflow.com/a/43190120/117471

2 Stimmen

Denken Sie daran, dass BASH keine Variablen wie $TAB in einfachen Anführungszeichen, Sie müssen es also in doppelten Anführungszeichen verwenden.

0 Stimmen

Vorsichtig bei der Verwendung von * innerhalb von Anführungszeichen... wird als glob behandelt, nicht als die von Ihnen beabsichtigte Regex.

34voto

Bruno Bronosky Punkte 60135

@sedit war auf dem richtigen Weg, aber es ist ein bisschen umständlich, eine Variable zu definieren.

Lösung (bash-spezifisch)

Der Weg, dies in der Bash zu tun, besteht darin, ein Dollarzeichen vor die in Anführungszeichen gesetzte Zeichenkette zu setzen.

$ echo -e '1\n2\n3'
1
2
3

$ echo -e '1\n2\n3' | sed 's/.*/\t&/g'
t1
t2
t3

$ echo -e '1\n2\n3' | sed $'s/.*/\t&/g'
    1
    2
    3

Wenn Ihre Zeichenkette eine Variablenerweiterung enthalten muss, können Sie Zeichenketten in Anführungszeichen wie folgt zusammenstellen:

$ timestamp=$(date +%s)
$ echo -e '1\n2\n3' | sed "s/.*/$timestamp"$'\t&/g'
1491237958  1
1491237958  2
1491237958  3

Erläuterung

In bash $'string' verursacht "ANSI-C-Erweiterung". Und das ist es, was die meisten von uns erwarten, wenn wir Dinge verwenden wie \t , \r , \n , usw. Von: https://www.gnu.org/software/bash/manual/html_node/ANSI_002dC-Quoting.html#ANSI_002dC-Quoting

Wörter der Form $'string' werden besonders behandelt. Das Wort erweitert sich zu String , wobei Zeichen mit Schrägstrich gemäß den Angaben in dem ANSI C-Standard. Backslash-Escape-Sequenzen, falls vorhanden, werden dekodiert...

Das erweiterte Ergebnis steht in einfachen Anführungszeichen, als ob das Dollarzeichen nicht vorhanden wäre nicht vorhanden gewesen wäre.

Lösung (wenn Sie bash vermeiden müssen)

Ich persönlich halte die meisten Bemühungen, Bash zu vermeiden, für albern, weil die Vermeidung von Bashismen Ihren Code NICHT* portabel macht. (Ihr Code wird weniger spröde sein, wenn Sie ihn in Shebang bash -eu als wenn Sie versuchen, die Bash zu vermeiden und die sh [es sei denn, Sie sind ein absoluter POSIX-Ninja].) Aber anstatt eine religiöse Diskussion darüber zu führen, werde ich Ihnen einfach die BESTE* Antwort geben.

$ echo -e '1\n2\n3' | sed "s/.*/$(printf '\t')&/g"
    1
    2
    3

* BESTE Antwort? Ja, denn ein Beispiel dafür, was die meisten Anti-Bash-Shell-Scripter in ihrem Code falsch machen würden, ist die Verwendung von echo '\t' wie in @robrecord's Antwort . Das funktioniert für GNU echo, aber nicht für BSD echo. Das wird von The Open Group erklärt unter http://pubs.opengroup.org/onlinepubs/9699919799/utilities/echo.html#tag_20_37_16 Und dies ist ein Beispiel dafür, warum der Versuch, Bashismen zu vermeiden, in der Regel scheitert.

9voto

Thomas Bratt Punkte 43640

Ich habe etwas Ähnliches mit einer Bash-Shell auf Ubuntu 12.04 (LTS) verwendet:

Anhängen einer neuen Zeile mit Registerkarte,zweite wenn erste übereinstimmt:

sed -i '/first/a \\t second' filename

Zu ersetzen erste con Registerkarte,zweite :

sed -i 's/first/\\t second/g' filename

4 Stimmen

Der doppelte Escape ist der Schlüssel, d.h. verwenden Sie \\t und nicht \t .

0 Stimmen

Außerdem musste ich unter Ubuntu 16.04 und Bash 4.3 doppelte Anführungszeichen anstelle von einfachen Anführungszeichen verwenden.

5voto

robrecord Punkte 344

Utilisez $(echo '\t') . Sie müssen das Muster in Anführungszeichen setzen.

Beispiel: So entfernen Sie eine Registerkarte:

sed "s/$(echo '\t')//"

6 Stimmen

Es ist lustig, dass Sie eine "GNU echo"-spezifische Funktion verwenden (Interpretation von \t als Tabulatorzeichen), um einen "BSD sed"-spezifischen Fehler zu beheben (Interpretation von \t als 2 getrennte Zeichen). Vermutlich, wenn Sie "GNU echo" haben, haben Sie auch "GNU sed". In diesem Fall bräuchten Sie echo nicht zu benutzen. Mit BSD echo echo '\t' wird 2 separate Zeichen ausgeben. Der POSIX-portable Weg ist die Verwendung von printf '\t' . Deshalb sage ich: Versuchen Sie nicht, Ihren Code portabel zu machen, indem Sie keine Bash verwenden. Es ist schwieriger als Sie denken. verwenden bash ist das Tragbarste, was die meisten von uns tun können.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X