Löschen Sie alle Kommentare in einer Datei mit sed

7

Wie würden Sie alle Kommentare mit sed aus einer Datei löschen (mit # definiert), wenn "#" in einer Zeichenkette steht?

Dies half sehr, außer für der String-Teil.

    
Logick 25.11.2012, 05:59
quelle

7 Antworten

10

Wenn # immer einen Kommentar bedeutet und irgendwo in einer Zeile vorkommen kann (wie nach irgendeinem Code):

%Vor%

Wenn Sie es an Ort und Stelle ändern möchten, fügen Sie den Schalter -i hinzu:

%Vor%

Dies wird von # bis zum Ende der Zeile gelöscht, wobei jeder Kontext ignoriert wird. Wenn du # irgendwo verwendest, wo es kein Kommentar ist (wie in einer Zeichenkette), wird es auch gelöscht.

Wenn Kommentare nur am Anfang einer Zeile beginnen können, tun Sie Folgendes:

%Vor%

Wenn ihnen Leerzeichen vorangehen, aber nichts anderes, tun Sie:

%Vor%

Diese beiden sind ein wenig sicherer, weil sie wahrscheinlich die gültige Verwendung von # in Ihrem Code nicht löschen, etwa in Strings.

Bearbeiten:

Es gibt nicht wirklich eine nette Art zu erkennen, ob etwas in einer Zeichenkette ist. Ich würde die letzten beiden verwenden, wenn das den Beschränkungen Ihrer Sprache entspricht.

Das Problem beim Erkennen, ob Sie in einer Zeichenfolge sind, ist, dass reguläre Ausdrücke nicht alles können. Es gibt ein paar Probleme:

  • Strings können sich wahrscheinlich über Linien erstrecken
  • Ein regulärer Ausdruck kann nicht den Unterschied zwischen Apostrophien und einfachen Anführungszeichen erkennen
  • Ein regulärer Ausdruck kann keine verschachtelten Anführungszeichen enthalten (diese Fälle verwirren die Regex):

    %Vor%

Wenn doppelte Anführungszeichen die einzige Möglichkeit sind, Zeichenfolgen zu definieren, werden doppelte Anführungszeichen nie in einem Kommentar erscheinen und Zeichenfolgen können sich nicht über mehrere Zeilen erstrecken. Versuchen Sie etwas wie folgt:

%Vor%

Das sind viele Voraussetzungen, aber wenn sie alle halten, sind Sie im Geschäft. Sonst, ich fürchte, du bist SOL, und du solltest besser in etwas wie Python schreiben, wo du fortgeschrittenere Logik machen kannst.

    
tjameson 25.11.2012 06:05
quelle
5

Dies könnte für Sie funktionieren (GNU sed):

%Vor%
  • /#/!b , wenn die Zeile kein # bail out
  • enthält
  • s/^/\n/ fügt einen eindeutigen Marker ( \n )
  • ein
  • ta;:a springt zu einem Loop-Label (setzt das Ersatz-True / False-Flag zurück)
  • s/\n$//;t wenn marker am Ende der Zeile, entferne und bail out
  • s/\n\(\("[^"]*"\)\|\('\''[^'\'']*'\''\)\)/\n/;ta , wenn der String, der auf den Marker folgt, ein in Anführungszeichen stehender String ist, kreuzen Sie den Marker vor ihm und loop.
  • s/\n\([^#]\)/\n/;ta , wenn das Zeichen, das der Markierung folgt, kein # ist, schiebe den Marker vor und loop.
  • s/\n.*// Der Rest der Zeile ist Kommentar, entfernen Sie den Marker und den Rest der Zeile.
potong 25.11.2012 12:48
quelle
3

Da es keine Beispieleingabe durch den Fragesteller gibt, nehme ich ein paar Fälle an und Bash ist die Eingabedatei, da bash als das Tag der Frage verwendet wird.

Fall 1 : ganze Zeile ist der Kommentar

Das Folgende sollte in den meisten Fällen ausreichen:

%Vor%

Es passt zu jeder Zeile, die keine oder mindestens eine führende Leerstelle hat (Leerzeichen, Tab oder einige andere, siehe man isspace ), gefolgt von # , dann lösche die Zeile nach d Befehl.

Alle Zeilen wie:

%Vor%

Sie werden gelöscht.

Aber

%Vor%

wird nicht gelöscht, was das gewünschte Ergebnis ist.

Fall 2 : Kommentar nach tatsächlichem Code

Zum Beispiel:

%Vor%

Der Kommentarteil kann durch

entfernt werden %Vor%

[^\"'] wird verwendet, um String-Verwechslungen in Anführungszeichen zu vermeiden, es bedeutet jedoch auch, dass Kommentare mit den Zitaten ' oder " nicht entfernt werden.

Finale sed

%Vor%     
livibetter 25.11.2012 08:12
quelle
2

Um Kommentarzeilen zu entfernen (Zeilen, deren erstes Nicht-Leerzeichen Zeichen # ist), aber nicht shebang Zeilen (Zeilen, deren erste Zeichen #! sind):

%Vor%

Das erste Argument von sed ist ein String, der ein sed-Programm enthält, das aus zwei delete-line-Befehlen der Form / regex /d besteht. Befehle sind durch ; getrennt. Der erste Befehl löscht Kommentarzeilen, aber keine Shebang-Zeilen. Der zweite Befehl löscht alle verbleibenden leeren Kommentarzeilen. Es verarbeitet keine nachgestellten Kommentare.

Das letzte Argument von sed ist eine Datei, die als Eingabe verwendet wird. In Bash können Sie auch mit einer String-Variablen wie dieser arbeiten:

%Vor%

Beispiel:

%Vor%

Ausgabe:

%Vor%     
jwfearn 19.02.2015 19:00
quelle
1

Wenn "in einer Zeichenfolge enthalten sein" bedeutet, dass "zwischen einem Paar von Anführungszeichen (Einzel- oder Doppelzeichen)" auftritt, kann die Frage wie "Alles nach dem ersten nicht aufgeführten # entfernen" umformuliert werden. Sie können die in Anführungszeichen gesetzten Strings wiederum als beliebige Werte zwischen zwei Anführungszeichen definieren, ausgenommen rückgestrichene Anführungszeichen. Als eine geringfügige Verfeinerung, ersetzen Sie die gesamte Zeile durch alles bis kurz vor dem ersten unquoted #.

Also erhalten wir für den trivialen Fall etwas wie [^\"'#] - ein Stück String, das weder ein Kommentarzeichen noch ein Backslash oder ein Anfangszitat ist. Dann können wir einen umgekehrten Schrägstrich akzeptieren, gefolgt von allem: \. - das ist kein Literalpunkt, das ist ein umgekehrter Schrägstrich, gefolgt von einem Punkt-Metazeichen, das mit jedem Zeichen übereinstimmt.

Dann können wir null oder mehr Wiederholungen einer Zeichenfolge in Anführungszeichen zulassen. Um einzelne oder doppelte Anführungszeichen zu akzeptieren, lassen Sie jeweils null oder mehr zu. Eine in Anführungszeichen gesetzte Zeichenfolge muss als Anführungszeichen definiert werden, gefolgt von null oder mehr entweder eines rückgestrichenen beliebigen Zeichens oder eines beliebigen Zeichens außer dem schließenden Zitat: "\(\.\|[^\"]\)*" oder ähnlich für einfach zitierte Strings '\(\.\|[^\']\)*' .

Wenn Sie all dies zusammenfügen, könnte Ihr sed -Skript etwa so aussehen:

%Vor%

Aber da es in Anführungszeichen gesetzt werden muss und sowohl einfache als auch doppelte Anführungszeichen in der Zeichenfolge enthalten sind, benötigen wir eine weitere zusätzliche Komplikation. Erinnern Sie sich daran, dass die Shell das Zusammenfügen von Strings wie "foo"'bar' wird ersetzt durch foobar - foo in doppelten Anführungszeichen und bar in einfachen Anführungszeichen ermöglicht. Sie können also einfache Anführungszeichen verwenden, indem Sie sie in doppelte Anführungszeichen neben der Zeichenfolge mit einem einfachen Anführungszeichen setzen - '"foo"'"'" ist "foo" in einfachen Anführungszeichen neben ' in Anführungszeichen, also "foo"' ; und "' kann als '"' neben "'" ausgedrückt werden. Und so kann ein String mit nur einem Anführungszeichen, der die doppelten Anführungszeichen foo"'bar enthält, mit 'foo"' neben "'bar" oder vielleicht realistischer für diesen Fall 'foo"' neben "'" neben einem anderen String mit einem Anführungszeichen% zitiert werden. co_de%, ergibt 'bar' .

%Vor%

Dies wurde unter Linux getestet; Auf anderen Plattformen kann sich der 'foo'"'"'bar' -Dialekt geringfügig unterscheiden. Beispielsweise müssen Sie möglicherweise die umgekehrten Schrägstriche vor den Gruppierungs- und Änderungsoperatoren weglassen.

Leider, wenn Sie mehrzeilige Strings in Anführungszeichen haben, wird dies nicht funktionieren; sed prüft standardmäßig nur jeweils eine Eingabezeile. Sie könnten ein komplexes Skript erstellen, das mehrere Zeilen in den Speicher sammelt, aber dann zu z.B. Perl macht sehr viel Sinn.

    
tripleee 25.11.2012 18:40
quelle
0

Wie Sie bereits erwähnt haben, funktioniert sed nicht gut, wenn Teile eines Skripts wie Kommentare aussehen, aber nicht. Zum Beispiel könnten Sie ein # innerhalb einer Zeichenkette finden, oder die ziemlich häufige $# und ${#param} .

Ich habe einen Shell-Formatierer namens shfmt geschrieben, der eine Funktion zur Code-Minimierung enthält. Dazu gehört das Entfernen von Kommentaren, unter anderem:

%Vor%

Der Parser und der Drucker sind Go-Pakete. Wenn Sie also eine benutzerdefinierte Lösung wünschen, sollte es ziemlich einfach sein, ein Go-Programm mit 20 Zeilen zu schreiben, um Kommentare genau so zu entfernen, wie Sie möchten.

    
Daniel Martí 11.03.2018 19:22
quelle
-1
%Vor%

Wenn die Zeilen mit einem einzelnen # Kommentar beginnen, entfernt der Befehl Above alle Kommentare aus der Datei.

    
Harshad Yeola 28.07.2014 07:52
quelle

Tags und Links