Löschen Sie alle Kommentare in einer Datei mit sed
Wie würden Sie das löschen aller Kommentare mit sed aus einer Datei(definiert mit #) mit Bezug auf '#' in einem string?
Diese half viel, außer für den string-Teil.
- Kann # sich in einem Kontext vor, um den Beginn eines Kommentars?
- Wie werden strings definiert? Wird ein string-Zeichen (wie ein Zitat) je in ein Kommentar?
- Wenn man Kommentare in ein shell-Skript, das Sie brauchen, zu kümmern, viel mehr als strings. Zum Beispiel, es gibt keinen Kommentar in
echo foo#bar
oderecho ${foo#bar} ${foo##bar}
. - Sie müssen auch befassen sich hier mit docs und mehrzeilige strings.
- Ich vergaß diese und
$#
und${#foobar}
.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Wenn
#
bedeutet immer einen Kommentar, und können an beliebiger Stelle in einer Zeile (wie nach einigen code):Wenn Sie möchten, ändern Sie es an Ort und Stelle, fügen Sie die
-i
Schalter:Diese löschen aus jedem
#
an das Ende der Zeile, ohne jeglichen Kontext. Wenn Sie#
überall dort, wo es nicht ein Kommentar (wie ein string), wird es löschen Sie das auch.Wenn Kommentare können nur am Anfang einer Zeile, so etwas wie dies tun:
Wenn Sie kann eingeleitet werden durch ein Leerzeichen, aber sonst nichts, tun:
Diese beiden werden sich auch ein wenig sicherer, weil Sie wahrscheinlich nicht löschen, gilt die Nutzung von
#
im code, wie in Zeichenfolgen.Edit:
Es ist nicht wirklich eine schöne Art, die erkennen, ob etwas in einem string. Ich würde die letzten beiden, wenn, das würde genügen den Beschränkungen Ihrer Sprache.
Das problem mit der Erkennung ob man in einem string ist, dass reguläre Ausdrücke können nicht alles tun. Es gibt ein paar Probleme:
Einem regulären Ausdruck kann nicht mit verschachtelten Zitaten (diese Fälle werden, verwirren den regex):
Wenn doppelte Anführungszeichen sind der einzige Weg, strings definiert sind, werden die doppelten Anführungszeichen wird nie erscheinen in einem Kommentar, und strings können mehrere Zeilen umfassen, probieren Sie etwas wie dieses:
Das ist eine Menge von pre-Bedingungen, aber, wenn Sie alle, Sie sind im Geschäft. Ansonsten bin ich Angst, du bist SOL, und Sie wäre besser, zu schreiben, es in etwas wie Python, wo Sie mehr tun können, erweiterte Logik.
sed 's:#[^"]*$::g' <file-name>
falsch entfernt alles, was nach dem#
imsed 's/\*/\*/g'
sed -e 's/^[ \t]*#[^!].*$//g' -e 's/[ \t]#.*$//g'
. Das vermeiden die meisten anderen Skript verwendet für #:echo "${#a} $# ${a#3} $(( 16#11 ))"
. `g
flag notwendig? Es ist nicht so, dass eine Zeile text haben mehrere Ende der Zeilen.Könnte dies für Sie arbeiten (GNU sed):
/#/!b
wenn die Zeile nicht enthalten#
- bail-out -s/^/\n/
legen Sie einen eindeutigen marker (\n
)ta;:a
Sprung in einen loop-label (setzt die ersetzen, true/false-flag)s/\n$//;t
wenn die Markierung am Ende der Zeile entfernen und bail-out -s/\n\(\("[^"]*"\)\|\('\''[^'\'']*'\''\)\)/\1\n/;ta
wenn der string nach dem marker ist eine börsennotierte ein, stoßen die marker nach vorne und Schleife.s/\n\([^#]\)/\1\n/;ta
wenn das Zeichen nach der Markierung ist nicht ein#
, stoßen die marker nach vorne und Schleife.s/\n.*//
der Rest der Zeile ist Kommentar, entfernen Sie die Markierung und der rest der Zeile.Da es kein Beispiel für die Eingabe zur Verfügung gestellt vom Fragesteller, ich gehe davon aus ein paar Fällen und Bash ist die input-Datei, da die bash benutzt wird, wie der tag von der Frage.
Fall 1: gesamte Zeile wird der Kommentar
Folgenden sollte ausreichend sein, in den meisten Fällen:
Es entspricht jede Zeile hat die keine hat oder zumindest eine führende white-space-Zeichen (Leerzeichen, Tabulator, oder ein paar andere, siehe
man isspace
), gefolgt von einem#
, dann löschen Sie die Zeile durchd
Befehl.Zeilen wie:
Werden Sie gelöscht.
Aber
werden nicht gelöscht, das ist das gewünschte Ergebnis.
Fall 2: Kommentar nach dem tatsächlichen code
Beispiel:
Den Kommentar-Teil kann entfernt werden, indem
[^\"']
wird verwendet, um zu verhindern, zitierte Zeichenfolge Verwirrung, aber es bedeutet auch, dass Kommentare mit Zitaten'
oder"
wird nicht entfernt werden.Letzte sed
#
in eine Zeichenfolge oder eine Zeichenfolge in Anführungszeichen allein, zumindest in der one-liner-string. Da der Fragesteller hat nicht angegeben, was genau der string ist, meine Antwort steht richtig.Entfernen von Kommentarzeilen (Zeilen, deren erstes nicht-whitespace-Zeichen ist
#
) aber nicht shebang-Zeilen (Zeilen, deren erstes Zeichen#!
):Das erste argument
sed
ist eine Zeichenfolge, die ein sed-Programm, bestehend aus zwei delete-line-Befehlen der form/
regex/d
. Kommandos werden, getrennt durch;
. Der erste Befehl löscht die Kommentar-Zeilen, aber nicht shebang-Zeilen. Der zweite Befehl löscht alle verbleibenden leeren Kommentarzeilen. Es behandelt nicht die nachfolgende Kommentare.Das Letzte argument für
sed
ist eine Datei als Eingabe verwenden. In der Bash können Sie auch betreiben, die auf eine string-variable wie diese:Beispiel:
Ausgabe:
Angenommen, dass "in einem string" bedeutet "tritt zwischen einem paar von Anführungszeichen, einfache oder doppelte", die Frage kann umformuliert werden als "entfernen Sie alles nach dem ersten nicht börsennotierten #". Sie können definieren, wie Zeichenfolgen in Anführungszeichen, die wiederum, wie alles zwischen zwei Anführungszeichen, ausgenommen backslashed Zitate. Als kleine Verfeinerung, ersetzen Sie die gesamte Zeile mit alles bis kurz vor dem ersten nicht börsennotierten #.
Also wir bekommen so etwas wie
[^\"'#]
für den trivialen Fall -- ein Stück Schnur, die weder einen Kommentar melden Sie noch einen backslash, noch eine öffnung zitieren. Dann können wir akzeptieren, ein backslash gefolgt von einem etwas:\\.
- das ist nicht eine wörtliche dot, das ist ein literal backslash, gefolgt von einem Punkt Metazeichen für ein beliebiges Zeichen.Dann können wir damit null oder mehr Wiederholungen von einer in Anführungszeichen eingeschlossenen Zeichenkette haben. Um zu akzeptieren, entweder einzelne oder doppelte Anführungszeichen erlauben die null oder mehr der einzelnen. Eine Zeichenfolge in Anführungszeichen wird definiert als eine öffnung quote, gefolgt von null oder mehr entweder für eine backslashed beliebiges Zeichen oder alle Zeichen mit Ausnahme der schließenden quote:
"\(\\.\|[^\"]\)*"
oder ähnlich für single-quoted strings'\(\\.\|[^\']\)*'
.Piecing all dies zusammen, Ihr
sed
- Skript könnte wie folgt Aussehen:Aber da braucht es zitiert zu werden, und sowohl einfache und doppelte Anführungszeichen sind im string enthalten, wir brauchen eine weitere Komplikation. Daran erinnern, dass die shell erlaubt, um zusammen zu kleben Zeichenfolgen wie
"foo"'bar'
wird ersetzt mitfoobar
--foo
in doppelte Anführungszeichen, undbar
in einfache Anführungszeichen gesetzt werden. So können Sie einzelne Zitate, indem Sie Sie in Anführungszeichen neben Ihrem single-quoted-string -'"foo"'"'"
ist"foo"
in einfache Anführungszeichen neben'
in doppelte Anführungszeichen, so"foo"'
; und"'
ausgedrückt werden kann, als'"'
neben"'"
. Und so eine single-quoted-string mit doppelten Anführungszeichenfoo"'bar
kann zitiert werden mit'foo"'
neben"'bar"
oder vielleicht realistischer für diesen Fall'foo"'
neben"'"
neben einem anderen single-quoted string'bar'
, was'foo'"'"'bar'
.Getestet wurde dies unter Linux, auf anderen Plattformen, die
sed
Dialekt etwas unterschiedlich sein. Zum Beispiel, müssen Sie möglicherweise das weglassen der Schrägstriche vor der Gruppierung und Veränderung Operatoren.Ach, wenn Sie multi-line-quoted strings, wird dies nicht funktionieren;
sed
per design nur untersucht, ein Eingabe-Zeile zu einem Zeitpunkt. Sie könnten bauen ein Komplexes script, das sammelt mehrere Zeilen in den Speicher, aber dann Umschalten auf z.B. Perl beginnt um sehr viel Sinn machen.Als Sie haben darauf hingewiesen, sed nicht gut funktionieren, wenn alle Teile des Skriptes sehen aus wie Kommentare, aber eigentlich gar nicht. Zum Beispiel konnte man ein # in einem string, oder die Recht verbreiteten
$#
und${#param}
.Schrieb ich ein shell-formatter genannt shfmt, das hat eine Funktion zum verkleinern von code. Das beinhaltet das entfernen von Kommentaren, unter anderem:
Den parser und printer sind packages, also, wenn Sie möchten, eine benutzerdefinierte Lösung, sollte es ziemlich einfach sein, schreiben einen 20-Zeilen-Programm Gehen, um Kommentare zu entfernen, die in die genaue Art und Weise, die Sie möchten.
Angenommen, dass die Linien startet mit single # Kommentar, Obigen Befehl entfernt alle Kommentare aus der Datei.