sed "s/\(.*\)/\t\1/" $filename > $sedTmpFile && mv $sedTmpFile $filename
Ich erwarte, dass dieses sedSkript tabvor jeder Zeile ein $filenameeinfügt, dies ist jedoch nicht der Fall. Aus irgendeinem Grund wird tstattdessen ein eingefügt.
Da sed zwischen den Plattformen variieren kann (insbesondere BSD / MacOSX im Vergleich zu Linux), kann es hilfreich sein, die Plattform anzugeben, auf der Sie sed verwenden.
Ah ja; zur Verdeutlichung: Nicht alle Versionen von sed verstehen \tim Ersatzteil des Ausdrucks (es wird \tim Mustervergleichsteil gut erkannt )
John Weldon
3
awwwwwwwwwwwwwwwwwww, ok das ist ziemlich interessant. Und seltsam. Warum sollten Sie es an einem Ort erkennen lassen, aber nicht am anderen ...?
Sixtyfootersdude
2
Von einem Skript aufgerufen, funktioniert das nicht: Tabs werden von sh ignoriert. Mit dem folgenden Code aus einem Shell-Skript wird beispielsweise $ TEXT_TO_ADD hinzugefügt, ohne dass eine Tabelle vorangestellt wird: sed "$ {LINE} a \\ $ TEXT_TO_ADD" $ FILE.
Sie waren auf dem richtigen Weg mit der $'string'aber fehlenden Erklärung. Tatsächlich vermute ich aufgrund der äußerst umständlichen Verwendung, dass Sie wahrscheinlich ein unvollständiges Verständnis haben (wie die meisten von uns mit Bash). Siehe meine Erklärung unten: stackoverflow.com/a/43190120/117471
Bruno Bronosky
1
Denken Sie daran, dass BASH Variablen nicht wie $TABin einfachen Anführungszeichen erweitert, daher müssen Sie doppelte Anführungszeichen verwenden.
Nealmcb
Vorsicht bei der Verwendung von *doppelten Anführungszeichen ... dies wird als Glob behandelt, nicht als Regex, den Sie beabsichtigen.
Levigroker
27
@sedit war auf dem richtigen Weg, aber es ist etwas umständlich, eine Variable zu definieren.
Lösung (Bash-spezifisch)
Die Möglichkeit, dies in Bash zu tun, besteht darin, ein Dollarzeichen vor Ihre einfache Anführungszeichenfolge zu setzen.
$ echo -e '1\n2\n3'123
$ echo -e '1\n2\n3'| sed 's/.*/\t&/g'
t1
t2
t3
$ echo -e '1\n2\n3'| sed $'s/.*/\t&/g'123
Wenn Ihre Zeichenfolge eine Variablenerweiterung enthalten muss, können Sie Zeichenfolgen in Anführungszeichen wie folgt zusammenstellen:
$ timestamp=$(date +%s)
$ echo -e '1\n2\n3'| sed "s/.*/$timestamp"$'\t&/g'149123795811491237958214912379583
Wörter der Form $ 'string' werden speziell behandelt. Das Wort wird zu Zeichenfolge erweitert , wobei Zeichen mit Backslash-Escapezeichen gemäß ANSI C-Standard ersetzt werden. Backslash-Escape-Sequenzen werden, falls vorhanden, dekodiert ...
Das erweiterte Ergebnis wird in einfachen Anführungszeichen gesetzt, als ob das Dollarzeichen 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 dumm, weil das Vermeiden von Bashismen Ihren Code NICHT portabel macht. (Ihr Code wird weniger spröde sein, wenn Sie ihn verprügeln, bash -euals wenn Sie versuchen, Bash zu vermeiden und zu verwenden sh[es sei denn, Sie sind ein absoluter POSIX-Ninja].) Aber anstatt ein religiöses Argument darüber zu haben, gebe ich Ihnen nur das BESTE * Antworten.
$ echo -e '1\n2\n3'| sed "s/.*/$(printf '\t')&/g"123
* 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 echo '\t'wie in der Antwort von @ robrecord . Das funktioniert für GNU-Echo, aber nicht für BSD-Echo. Dies wird von The Open Group unter http://pubs.opengroup.org/onlinepubs/9699919799/utilities/echo.html#tag_20_37_16 erklärt . Dies ist ein Beispiel dafür, warum der Versuch, Bashismen zu vermeiden, normalerweise fehlschlägt.
Es ist lustig, dass Sie eine "GNU-Echo" -spezifische Funktion verwenden (\ t als Tabulatorzeichen interpretieren), um einen "BSD sed" -spezifischen Fehler zu beheben (\ t als 2 separate Zeichen interpretieren). Wenn Sie "GNU-Echo" haben, hätten Sie vermutlich auch "GNU sed". In diesem Fall müssten Sie kein Echo verwenden. Mit BSD gibt echo echo '\t'2 separate Zeichen aus. Die tragbare Methode von POSIX ist die Verwendung printf '\t'. Deshalb sage ich: Versuchen Sie nicht, Ihren Code portabel zu machen, indem Sie keine Bash verwenden. Es ist schwieriger als du denkst. Verwenden bashist das tragbarste, was die meisten von uns tun können.
Bruno Bronosky
3
Sie müssen keine sedErsetzung durchführen, wenn Sie tatsächlich nur eine Registerkarte vor der Zeile einfügen möchten. Das Ersetzen dieses Falls ist im Vergleich zum Ausdrucken ein teurer Vorgang, insbesondere wenn Sie mit großen Dateien arbeiten. Es ist auch einfacher zu lesen, da es kein Regex ist.
sedunterstützt nicht \t, noch andere Escape-Sequenzen wie \nfür diese Angelegenheit. Die einzige Möglichkeit, die ich gefunden habe, bestand darin, das Tabulatorzeichen mithilfe von in das Skript einzufügensed .
Möglicherweise möchten Sie jedoch Perl oder Python verwenden. Hier ist ein kurzes Python-Skript, das ich geschrieben habe und das ich für alle Stream-Regexing verwende:
Ich denke, andere haben dies für andere Ansätze angemessen geklärt ( sed,AWK usw.). Es bashfolgen jedoch meine spezifischen Antworten (getestet unter macOS High Sierra und CentOS 6/7).
1) Wenn OP eine Such- und Ersetzungsmethode verwenden möchte, die der ursprünglich vorgeschlagenen ähnelt, würde ich vorschlagen, perldiese wie folgt zu verwenden. Hinweise: Backslashes vor Klammern für Regex sollten nicht erforderlich sein. Diese Codezeile zeigt, wie sie $1besser verwendet werden kann als \1mit dem perlSubstitutionsoperator (z. B. gemäß Perl 5-Dokumentation ).
2) Wie jedoch von ghostdog74 hervorgehoben , würde ich , da die gewünschte Operation darin besteht, einfach eine Registerkarte am Anfang jeder Zeile hinzuzufügen , bevor die tmp-Datei in die Eingabe- / Zieldatei ( $filename) geändert wird , perlerneut empfehlen , jedoch mit der folgenden Änderung (s):
3) Natürlich ist die tmp-Datei überflüssig , daher ist es besser, einfach alles an Ort und Stelle zu tun ( -iFlag hinzufügen ) und die Dinge zu einem eleganteren Einzeiler zu vereinfachen
Antworten:
Nicht alle Versionen von
sed
verstehen\t
. Fügen Sie stattdessen einfach eine wörtliche Registerkarte ein (drücken Sie Ctrl- Vdann Tab).quelle
\t
im Ersatzteil des Ausdrucks (es wird\t
im Mustervergleichsteil gut erkannt )Mit Bash können Sie ein TAB-Zeichen programmgesteuert wie folgt einfügen:
quelle
$'string'
aber fehlenden Erklärung. Tatsächlich vermute ich aufgrund der äußerst umständlichen Verwendung, dass Sie wahrscheinlich ein unvollständiges Verständnis haben (wie die meisten von uns mit Bash). Siehe meine Erklärung unten: stackoverflow.com/a/43190120/117471$TAB
in einfachen Anführungszeichen erweitert, daher müssen Sie doppelte Anführungszeichen verwenden.*
doppelten Anführungszeichen ... dies wird als Glob behandelt, nicht als Regex, den Sie beabsichtigen.@sedit war auf dem richtigen Weg, aber es ist etwas umständlich, eine Variable zu definieren.
Lösung (Bash-spezifisch)
Die Möglichkeit, dies in Bash zu tun, besteht darin, ein Dollarzeichen vor Ihre einfache Anführungszeichenfolge zu setzen.
Wenn Ihre Zeichenfolge eine Variablenerweiterung enthalten muss, können Sie Zeichenfolgen in Anführungszeichen wie folgt zusammenstellen:
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-QuotingLösung (wenn Sie Bash vermeiden müssen)
Ich persönlich halte die meisten Bemühungen, Bash zu vermeiden, für dumm, weil das Vermeiden von Bashismen Ihren Code NICHT portabel macht. (Ihr Code wird weniger spröde sein, wenn Sie ihn verprügeln,
bash -eu
als wenn Sie versuchen, Bash zu vermeiden und zu verwendensh
[es sei denn, Sie sind ein absoluter POSIX-Ninja].) Aber anstatt ein religiöses Argument darüber zu haben, gebe ich Ihnen nur das BESTE * Antworten.* 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
echo '\t'
wie in der Antwort von @ robrecord . Das funktioniert für GNU-Echo, aber nicht für BSD-Echo. Dies wird von The Open Group unter http://pubs.opengroup.org/onlinepubs/9699919799/utilities/echo.html#tag_20_37_16 erklärt . Dies ist ein Beispiel dafür, warum der Versuch, Bashismen zu vermeiden, normalerweise fehlschlägt.quelle
Ich habe so etwas mit einer Bash-Shell unter Ubuntu 12.04 (LTS) verwendet:
So fügen Sie eine neue Zeile mit der Registerkarte hinzu: die zweite, wenn die erste übereinstimmt:
So ersetzen Sie zuerst mit Registerkarte zweiten :
quelle
\\t
und nicht\t
.Verwenden
$(echo '\t')
. Sie benötigen Anführungszeichen um das Muster.Z.B. So entfernen Sie eine Registerkarte:
quelle
echo '\t'
2 separate Zeichen aus. Die tragbare Methode von POSIX ist die Verwendungprintf '\t'
. Deshalb sage ich: Versuchen Sie nicht, Ihren Code portabel zu machen, indem Sie keine Bash verwenden. Es ist schwieriger als du denkst. Verwendenbash
ist das tragbarste, was die meisten von uns tun können.Sie müssen keine
sed
Ersetzung durchführen, wenn Sie tatsächlich nur eine Registerkarte vor der Zeile einfügen möchten. Das Ersetzen dieses Falls ist im Vergleich zum Ausdrucken ein teurer Vorgang, insbesondere wenn Sie mit großen Dateien arbeiten. Es ist auch einfacher zu lesen, da es kein Regex ist.zB mit awk
quelle
Ich habe dies auf dem Mac verwendet:
Verwendete diesen Link als Referenz
quelle
sed
unterstützt nicht\t
, noch andere Escape-Sequenzen wie\n
für diese Angelegenheit. Die einzige Möglichkeit, die ich gefunden habe, bestand darin, das Tabulatorzeichen mithilfe von in das Skript einzufügensed
.Möglicherweise möchten Sie jedoch Perl oder Python verwenden. Hier ist ein kurzes Python-Skript, das ich geschrieben habe und das ich für alle Stream-Regexing verwende:
quelle
Anstelle von BSD sed verwende ich Perl:
quelle
Ich denke, andere haben dies für andere Ansätze angemessen geklärt (
sed
,AWK
usw.). Esbash
folgen jedoch meine spezifischen Antworten (getestet unter macOS High Sierra und CentOS 6/7).1) Wenn OP eine Such- und Ersetzungsmethode verwenden möchte, die der ursprünglich vorgeschlagenen ähnelt, würde ich vorschlagen,
perl
diese wie folgt zu verwenden. Hinweise: Backslashes vor Klammern für Regex sollten nicht erforderlich sein. Diese Codezeile zeigt, wie sie$1
besser verwendet werden kann als\1
mit demperl
Substitutionsoperator (z. B. gemäß Perl 5-Dokumentation ).2) Wie jedoch von ghostdog74 hervorgehoben , würde ich , da die gewünschte Operation darin besteht, einfach eine Registerkarte am Anfang jeder Zeile hinzuzufügen , bevor die tmp-Datei in die Eingabe- / Zieldatei (
$filename
) geändert wird ,perl
erneut empfehlen , jedoch mit der folgenden Änderung (s):3) Natürlich ist die tmp-Datei überflüssig , daher ist es besser, einfach alles an Ort und Stelle zu tun (
-i
Flag hinzufügen ) und die Dinge zu einem eleganteren Einzeiler zu vereinfachenquelle