Kommentare aus Skriptzeile entfernen

    • Offizieller Beitrag

    Hi,
    es geht nicht darum die Kommentare generell zu löschen, sondern beim Lesen einer Skriptzeile nur den reinen Skriptanteil zu parsen.
    Bisher habe ich das immer mit LUA gelöst (da ist es am Einfachsten :D). Da in Rosetta Code aber eine derartige Aufgabe bestand habe ich das nun in AutoIt gelöst.
    Hier geht es nur um die Zeilen-Kommentare ( mit ; ), Blockkommentare sind davon nicht betroffen.

    Ein Zeilenkommentar beginnt mit einem Semikolon.
    Aber es kann sein, dass ein Semikolon Bestandteil eines Stringparameters in einem Funktionsaufruf/ einer Funktionsdeklaration oder in einer Zuweisung ist.
    Das bedeutet: Der Kommentar beginnt mit dem ersten Semikolon ausserhalb eines Strings.

    Spoiler anzeigen
    [autoit]

    Dim $aLines[4] = _
    [ _
    "$a = $b + $c ; Comment line 1", _
    "Dim $s1 = 'some text; tiled with semicolon', $s2 = 'another text; also tiled with semicolon' ; Comment line 2 - semicolon as part of assignment", _
    "_SomeFunctionCall('string parameter with ;', $anotherParam) ; Comment line 3 - semicolon as part parameter in an function call", _
    "Func _AnotherFunction($param1=';', $param2=';', $param3=';') ; Comment line 4 - semicolon as default value in parameter of a function headline" _
    ]

    [/autoit] [autoit][/autoit] [autoit]

    For $i = 0 To 3
    ConsoleWrite('+> Line ' & $i+1 & ' full:' & @CRLF & '+>' & $aLines[$i] & @CRLF)
    ConsoleWrite('!> without comment:' & @CRLF & '!>' & _LineStripComment($aLines[$i]) & @CRLF & @CRLF)
    Next

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    Func _LineStripComment($_Line)
    ; == tile line by all included comment marker
    Local $aPartsWithMarker = StringSplit($_Line, ';')
    Local $sNoComment

    [/autoit] [autoit][/autoit] [autoit]

    ; == if no comment marker: return full line
    If $aPartsWithMarker[0] = 0 Then Return $_Line

    [/autoit] [autoit][/autoit] [autoit]

    ; == check if string in part, if is'nt: following part(s) are comment
    For $i = 1 To $aPartsWithMarker[0]
    If Not StringRegExp($aPartsWithMarker[$i], "('|\x22)") Then
    If $i = 1 Then
    Return StringStripWS($aPartsWithMarker[$i], 2)
    Else
    Return StringStripWS($sNoComment & $aPartsWithMarker[$i], 2)
    EndIf
    Else
    ; == check if next leftside string delimiter has uneven count
    Local $iLen = StringLen($aPartsWithMarker[$i])
    Local $fDetectDelim = False, $sStringDelim, $iDelimCount, $sCurr
    For $j = $iLen To 1 Step -1
    $sCurr = StringMid($aPartsWithMarker[$i], $j, 1)
    If Not $fDetectDelim Then
    If $sCurr = "'" Or $sCurr = '"' Then
    $sStringDelim = $sCurr
    $iDelimCount += 1
    $fDetectDelim = True
    EndIf
    Else
    If $sCurr = $sStringDelim Then $iDelimCount += 1
    EndIf
    Next
    If Mod($iDelimCount, 2) Then
    ; == uneven count: so it masks the comment marker
    $sNoComment &= $aPartsWithMarker[$i] & ';'
    Else
    ; == even count: all following is comment
    Return StringStripWS($sNoComment & $aPartsWithMarker[$i], 2)
    EndIf
    EndIf
    Next
    EndFunc ;==>_LineStripComment

    [/autoit]
  • Oder via RegExp:

    [autoit]

    StringRegExpReplace($sScript, '(?x)(?:\r?\n?\s*;.*)|' & '((?>"[^"]*")+|' & "(?>'[^']*')+)", "\1")

    [/autoit]

    bzw. um alle Kommentare aus dem kompletten Code zu entfernen:

    [autoit]

    Func _RemoveComments(ByRef $sScript)
    $sScript = StringRegExpReplace($sScript, '(?x)(?:\r?\n?\s*;.*)|' & '((?>"[^"]*")+|' & "(?>'[^']*')+)", "\1") ;entferne ;-Komments
    $sScript = StringRegExpReplace($sScript, '(?i)(?:[\r\n]\s*)(\#ce|\#comments-end)(.*)', '$1') ;manche #ce haben noch Text dahinter
    $sScript = StringRegExpReplace($sScript, '(?x)(?:\r?\n?\s*;.*)|(?s)\r?\n?\s*\#c(?>s|omments-start)(?>(?>"[^"]*")+|' & "(?>'[^']*')+|.)*?\#c(?>e|omments-end)(?-s)|" & '((?>"[^"]*")+|' & "(?>'[^']*')+)", "\1")
    EndFunc ;==>_RemoveComments

    [/autoit]


    :D