-
Notifications
You must be signed in to change notification settings - Fork 122
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Update .CesarHackGray #14
Open
minkhantkyaw336
wants to merge
1
commit into
Cesar-Hack-Gray:master
Choose a base branch
from
minkhantkyaw336:patch-1
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Conversation
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/python import sys class BashFileIterator: class _Delimiter(object): def __init__(self, character, _type=''): self.character = character # type may be 'AP' or 'AS' (Arithmetic Expansion delimited by (()) or [] respectively), # 'S' (Command Substitution) or 'P' (Parameter Expansion) # type is set only for parenthesis or curly brace and square brace that opens group # e.g. in this statement $((1+2)) only the 1st '(' will have type ('AP') self.type = _type def is_group_opening(self): return bool(self.type or self.character in ("'", '"', '`')) def __eq__(self, other): if isinstance(other, BashFileIterator._Delimiter): return other.character == self.character elif isinstance(other, basestring): return other == self.character return False def __ne__(self, other): return not self.__eq__(other) def __str__(self): return self.character __repr__ = __str__ def __init__(self, src): self.src = src self.reset() def reset(self): self.pos = 0 self.insideComment = False self.insideHereDoc = False # possible characters in stack: # (, ) -- means Arithmetic Expansion or Command Substitution # {, } -- means Parameter Expansion # [, ] -- means Arithmetic Expansion # ` -- means Command Substitution # ' -- means single-quoted string # " -- means double-quoted string self._delimiters_stack = [] self._indices_of_escaped_characters = set() def getLastGroupOpeningDelimiter(self): return next((d for d in reversed(self._delimiters_stack) if d.is_group_opening()), BashFileIterator._Delimiter('')) def pushDelimiter(self, character, _type=''): d = BashFileIterator._Delimiter(character, _type=_type) last_opening = self.getLastGroupOpeningDelimiter() last = self._delimiters_stack[-1] if len(self._delimiters_stack) > 0 else BashFileIterator._Delimiter('') if d in ('{', '}'): if _type != '': # delimiter that opens group self._delimiters_stack.append(d) elif d == '}' and last == '{': self._delimiters_stack.pop() elif d in ('(', ')'): if _type != '': # delimiter that opens group self._delimiters_stack.append(d) elif last_opening == '(': if last == '(' and d == ')': self._delimiters_stack.pop() else: self._delimiters_stack.append(d) elif d in ('[', ']'): if _type != '': # delimiter that opens group self._delimiters_stack.append(d) elif last_opening == '[': if last == '[' and d == ']': self._delimiters_stack.pop() else: self._delimiters_stack.append(d) elif d == "'" and last_opening != '"' or d == '"' and last_opening != "'" or d == '`': if d == last_opening: self._delimiters_stack.pop() else: self._delimiters_stack.append(d) def isInsideGroup(self): return len(self._delimiters_stack) != 0 def getPreviousCharacters(self, n, should_not_start_with_escaped=True): """ 'should_not_start_with_escaped' means return empty string if the first character is escaped """ first_character_index = max(0, self.pos - n) if first_character_index in self._indices_of_escaped_characters: return '' else: return self.src[max(0, self.pos - n):self.pos] def getPreviousCharacter(self, should_not_start_with_escaped=True): return self.getPreviousCharacters(1, should_not_start_with_escaped=should_not_start_with_escaped) def getNextCharacters(self, n): return self.src[self.pos + 1:self.pos + n + 1] def getNextCharacter(self): return self.getNextCharacters(1) def getPreviousWord(self): word = '' i = 1 while i <= self.pos: newWord = self.getPreviousCharacters(i) if not newWord.isalpha(): break word = newWord i += 1 return word def getNextWord(self): word = '' i = 1 while self.pos + i < len(self.src): newWord = self.getNextCharacters(i) if not newWord.isalpha(): break word = newWord i += 1 return word def getPartOfLineAfterPos(self, skip=0): result = '' i = self.pos + 1 + skip while i < len(self.src) and self.src[i] != '\n': result += self.src[i] i += 1 return result def getPartOfLineBeforePos(self, skip=0): result = '' i = self.pos - 1 - skip while i >= 0 and self.src[i] != '\n': result = self.src[i] + result i -= 1 return result def charactersGenerator(self): hereDocWord = '' _yieldNextNCharactersAsIs = 0 def close_heredoc(): self.insideHereDoc = False callbacks_after_yield = [] while self.pos < len(self.src): ch = self.src[self.pos] if _yieldNextNCharactersAsIs > 0: _yieldNextNCharactersAsIs -= 1 elif ch == "\\" and not self.isEscaped(): self._indices_of_escaped_characters.add(self.pos + 1) else: if ch == "\n" and not self.isInsideSingleQuotedString() and not self.isInsideDoubleQuotedString(): # handle end of comments and heredocs if self.insideComment: self.insideComment = False elif self.insideHereDoc and self.getPartOfLineBeforePos() == hereDocWord: callbacks_after_yield.append(close_heredoc) elif not self.isInsideComment() and not self.isInsideHereDoc(): if ch in ('"', "'"): # single quote can't be escaped inside single-quoted string if not self.isEscaped() or ch == "'" and self.isInsideSingleQuotedString(): self.pushDelimiter(ch) elif not self.isInsideSingleQuotedString(): if not self.isEscaped(): if ch == "#" and not self.isInsideGroup() and \ (self.getPreviousCharacter() in ('\n', '\t', ' ', ';') or self.pos == 0): # handle comments self.insideComment = True elif ch == '`': self.pushDelimiter(ch) elif ch == '$': next_char = self.getNextCharacter() if next_char in ('{', '(', '['): next_2_chars = self.getNextCharacters(2) _type = 'AP' if next_2_chars == '((' else {'{': 'P', '(': 'S', '[': 'AS'}[next_char] self.pushDelimiter(next_char, _type=_type) _yieldNextNCharactersAsIs = 1 elif ch in ('{', '}', '(', ')', '[', ']'): self.pushDelimiter(ch) elif ch == '<' and self.getNextCharacter() == '<' and not self.isInsideGroup(): _yieldNextNCharactersAsIs = 1 # we should handle correctly heredocs and herestrings like this one: # echo <<< one if self.getNextCharacters(2) != '<<': # heredoc self.insideHereDoc = True hereDocWord = self.getPartOfLineAfterPos(skip=1) if hereDocWord[0] == '-': hereDocWord = hereDocWord[1:] hereDocWord = hereDocWord.strip().replace('"', '').replace("'", '') yield ch while len(callbacks_after_yield) > 0: callbacks_after_yield.pop()() self.pos += 1 assert not self.isInsideGroup(), 'Invalid syntax' raise StopIteration def isEscaped(self): return self.pos in self._indices_of_escaped_characters def isInsideDoubleQuotedString(self): return self.getLastGroupOpeningDelimiter() == '"' def isInsideSingleQuotedString(self): return self.getLastGroupOpeningDelimiter() == "'" def isInsideComment(self): return self.insideComment def isInsideHereDoc(self): return self.insideHereDoc def isInsideParameterExpansion(self): return self.getLastGroupOpeningDelimiter() == '{' def isInsideArithmeticExpansion(self): return self.getLastGroupOpeningDelimiter().type in ('AP', 'AS') def isInsideCommandSubstitution(self): last_opening_delimiter = self.getLastGroupOpeningDelimiter() return last_opening_delimiter == '`' or last_opening_delimiter.type == 'S' def isInsideAnything(self): return self.isInsideGroup() or self.insideHereDoc or self.insideComment def isInsideGroupWhereWhitespacesCannotBeTruncated(self): return self.isInsideComment() or self.isInsideDoubleQuotedString() or self.isInsideDoubleQuotedString() or \ self.isInsideHereDoc() or self.isInsideParameterExpansion() def minify(src): # first: remove all comments it = BashFileIterator(src) src = "" # result for ch in it.charactersGenerator(): if not it.isInsideComment(): src += ch # secondly: remove empty strings, strip lines and truncate spaces (replace groups of whitespaces by single space) it = BashFileIterator(src) src = "" # result emptyLine = True # means that no characters has been printed in current line so far previousSpacePrinted = True for ch in it.charactersGenerator(): if it.isInsideSingleQuotedString(): # first of all check single quoted string because line continuation does not work inside src += ch elif ch == "\\" and not it.isEscaped() and it.getNextCharacter() == "\n": # then check line continuation # line continuation will occur on the next iteration. just skip this backslash continue elif ch == "\n" and it.isEscaped(): # line continuation occurred # backslash at the very end of line means line continuation # so remove previous backslash and skip current newline character ch continue elif it.isInsideGroupWhereWhitespacesCannotBeTruncated() or it.isEscaped(): src += ch elif ch in (' ', '\t') and not previousSpacePrinted and not emptyLine and \ not it.getNextCharacter() in (' ', '\t', '\n'): src += " " previousSpacePrinted = True elif ch == "\n" and it.getPreviousCharacter() != "\n" and not emptyLine: src += ch previousSpacePrinted = True emptyLine = True elif ch not in (' ', '\t', '\n'): src += ch previousSpacePrinted = False emptyLine = False # thirdly: get rid of newlines it = BashFileIterator(src) src = "" # result for ch in it.charactersGenerator(): if it.isInsideAnything() or ch != "\n": src += ch else: prevWord = it.getPreviousWord() nextWord = it.getNextWord() if it.getNextCharacter() == '{': # functions declaration, see test t8.sh if it.getPreviousCharacter() == ')': continue else: src += ' ' elif prevWord in ("until", "while", "then", "do", "else", "in", "elif", "if") or \ nextWord in ("in",) or \ it.getPreviousCharacter() in ("{", "(") or \ it.getPreviousCharacters(2) in ("&&", "||"): src += " " elif nextWord in ("esac",) and it.getPreviousCharacters(2) != ';;': if it.getPreviousCharacter() == ';': src += ';' else: src += ';;' elif it.getNextCharacter() != "" and it.getPreviousCharacter() not in (";", '|'): src += ";" # finally: remove spaces around semicolons and pipes and other delimiters it = BashFileIterator(src) src = "" # result other_delimiters = ('|', '&', ';', '<', '>', '(', ')') # characters that may not be surrounded by whitespaces for ch in it.charactersGenerator(): if it.isInsideGroupWhereWhitespacesCannotBeTruncated(): src += ch elif ch in (' ', '\t') \ and (it.getPreviousCharacter() in other_delimiters or it.getNextCharacter() in other_delimiters) \ and it.getNextCharacters(2) not in ('<(', '>('): # process substitution # see test t_process_substitution.sh for details continue else: src += ch return src if __name__ == "__main__": # https://www.gnu.org/software/bash/manual/html_node/Reserved-Word-Index.html # http://pubs.opengroup.org/onlinepubs/009695399/utilities/xcu_chap02.html # http://pubs.opengroup.org/onlinepubs/9699919799/ # get bash source from file or from stdin src = "" if len(sys.argv) > 1: with open(sys.argv[1], "r") as ifile: src = ifile.read() else: src = sys.stdin.read() # use stdout.write instead of print to avoid newline at the end (print with comma at the end does not work) sys.stdout.write(minify(src)) # important rules: # 1. A single-quote cannot occur within single-quotes. # 2. The input characters within the double-quoted string that are also enclosed between "$(" and the matching ')' # shall not be affected by the double-quotes, but rather shall define that command whose output replaces the "$(...)" # when the word is expanded. # 3. Within the double-quoted string of characters from an enclosed "${" to the matching '}', an even number of # unescaped double-quotes or single-quotes, if any, shall occur. A preceding <backslash> character shall be used # to escape a literal '{' or '}' # 4.
Hola te saluda Cesar Hack Gray
Esos archivos no son los que manejan socialsploit las puse ahi por error, y
no son escritas por mi
Att... Cesar
El mar., 19 de enero de 2021 12:43 a. m., Casparlay <
notifications@github.com> escribió:
… #!/usr/bin/python
import sys
class BashFileIterator:
class _Delimiter(object):
def *init*(self, character, _type=''):
self.character = character
# type may be 'AP' or 'AS' (Arithmetic Expansion delimited by (()) or []
respectively),
# 'S' (Command Substitution) or 'P' (Parameter Expansion)
# type is set only for parenthesis or curly brace and square brace that
opens group
# e.g. in this statement $((1+2)) only the 1st '(' will have type ('AP')
self.type = _type
def is_group_opening(self):
return bool(self.type or self.character in ("'", '"', '`'))
def __eq__(self, other):
if isinstance(other, BashFileIterator._Delimiter):
return other.character == self.character
elif isinstance(other, basestring):
return other == self.character
return False
def __ne__(self, other):
return not self.__eq__(other)
def __str__(self):
return self.character
__repr__ = __str__
def __init__(self, src):
self.src = src
self.reset()
def reset(self):
self.pos = 0
self.insideComment = False
self.insideHereDoc = False
# possible characters in stack:
# (, ) -- means Arithmetic Expansion or Command Substitution
# {, } -- means Parameter Expansion
# [, ] -- means Arithmetic Expansion
# ` -- means Command Substitution
# ' -- means single-quoted string
# " -- means double-quoted string
self._delimiters_stack = []
self._indices_of_escaped_characters = set()
def getLastGroupOpeningDelimiter(self):
return next((d for d in reversed(self._delimiters_stack) if d.is_group_opening()),
BashFileIterator._Delimiter(''))
def pushDelimiter(self, character, _type=''):
d = BashFileIterator._Delimiter(character, _type=_type)
last_opening = self.getLastGroupOpeningDelimiter()
last = self._delimiters_stack[-1] if len(self._delimiters_stack) > 0 else BashFileIterator._Delimiter('')
if d in ('{', '}'):
if _type != '': # delimiter that opens group
self._delimiters_stack.append(d)
elif d == '}' and last == '{':
self._delimiters_stack.pop()
elif d in ('(', ')'):
if _type != '': # delimiter that opens group
self._delimiters_stack.append(d)
elif last_opening == '(':
if last == '(' and d == ')':
self._delimiters_stack.pop()
else:
self._delimiters_stack.append(d)
elif d in ('[', ']'):
if _type != '': # delimiter that opens group
self._delimiters_stack.append(d)
elif last_opening == '[':
if last == '[' and d == ']':
self._delimiters_stack.pop()
else:
self._delimiters_stack.append(d)
elif d == "'" and last_opening != '"' or d == '"' and last_opening != "'" or d == '`':
if d == last_opening:
self._delimiters_stack.pop()
else:
self._delimiters_stack.append(d)
def isInsideGroup(self):
return len(self._delimiters_stack) != 0
def getPreviousCharacters(self, n, should_not_start_with_escaped=True):
"""
'should_not_start_with_escaped' means return empty string if the first character is escaped
"""
first_character_index = max(0, self.pos - n)
if first_character_index in self._indices_of_escaped_characters:
return ''
else:
return self.src[max(0, self.pos - n):self.pos]
def getPreviousCharacter(self, should_not_start_with_escaped=True):
return self.getPreviousCharacters(1, should_not_start_with_escaped=should_not_start_with_escaped)
def getNextCharacters(self, n):
return self.src[self.pos + 1:self.pos + n + 1]
def getNextCharacter(self):
return self.getNextCharacters(1)
def getPreviousWord(self):
word = ''
i = 1
while i <= self.pos:
newWord = self.getPreviousCharacters(i)
if not newWord.isalpha():
break
word = newWord
i += 1
return word
def getNextWord(self):
word = ''
i = 1
while self.pos + i < len(self.src):
newWord = self.getNextCharacters(i)
if not newWord.isalpha():
break
word = newWord
i += 1
return word
def getPartOfLineAfterPos(self, skip=0):
result = ''
i = self.pos + 1 + skip
while i < len(self.src) and self.src[i] != '\n':
result += self.src[i]
i += 1
return result
def getPartOfLineBeforePos(self, skip=0):
result = ''
i = self.pos - 1 - skip
while i >= 0 and self.src[i] != '\n':
result = self.src[i] + result
i -= 1
return result
def charactersGenerator(self):
hereDocWord = ''
_yieldNextNCharactersAsIs = 0
def close_heredoc():
self.insideHereDoc = False
callbacks_after_yield = []
while self.pos < len(self.src):
ch = self.src[self.pos]
if _yieldNextNCharactersAsIs > 0:
_yieldNextNCharactersAsIs -= 1
elif ch == "\\" and not self.isEscaped():
self._indices_of_escaped_characters.add(self.pos + 1)
else:
if ch == "\n" and not self.isInsideSingleQuotedString() and not self.isInsideDoubleQuotedString():
# handle end of comments and heredocs
if self.insideComment:
self.insideComment = False
elif self.insideHereDoc and self.getPartOfLineBeforePos() == hereDocWord:
callbacks_after_yield.append(close_heredoc)
elif not self.isInsideComment() and not self.isInsideHereDoc():
if ch in ('"', "'"):
# single quote can't be escaped inside single-quoted string
if not self.isEscaped() or ch == "'" and self.isInsideSingleQuotedString():
self.pushDelimiter(ch)
elif not self.isInsideSingleQuotedString():
if not self.isEscaped():
if ch == "#" and not self.isInsideGroup() and \
(self.getPreviousCharacter() in ('\n', '\t', ' ', ';') or self.pos == 0):
# handle comments
self.insideComment = True
elif ch == '`':
self.pushDelimiter(ch)
elif ch == '$':
next_char = self.getNextCharacter()
if next_char in ('{', '(', '['):
next_2_chars = self.getNextCharacters(2)
_type = 'AP' if next_2_chars == '((' else {'{': 'P', '(': 'S', '[': 'AS'}[next_char]
self.pushDelimiter(next_char, _type=_type)
_yieldNextNCharactersAsIs = 1
elif ch in ('{', '}', '(', ')', '[', ']'):
self.pushDelimiter(ch)
elif ch == '<' and self.getNextCharacter() == '<' and not self.isInsideGroup():
_yieldNextNCharactersAsIs = 1
# we should handle correctly heredocs and herestrings like this one:
# echo <<< one
if self.getNextCharacters(2) != '<<':
# heredoc
self.insideHereDoc = True
hereDocWord = self.getPartOfLineAfterPos(skip=1)
if hereDocWord[0] == '-':
hereDocWord = hereDocWord[1:]
hereDocWord = hereDocWord.strip().replace('"', '').replace("'", '')
yield ch
while len(callbacks_after_yield) > 0:
callbacks_after_yield.pop()()
self.pos += 1
assert not self.isInsideGroup(), 'Invalid syntax'
raise StopIteration
def isEscaped(self):
return self.pos in self._indices_of_escaped_characters
def isInsideDoubleQuotedString(self):
return self.getLastGroupOpeningDelimiter() == '"'
def isInsideSingleQuotedString(self):
return self.getLastGroupOpeningDelimiter() == "'"
def isInsideComment(self):
return self.insideComment
def isInsideHereDoc(self):
return self.insideHereDoc
def isInsideParameterExpansion(self):
return self.getLastGroupOpeningDelimiter() == '{'
def isInsideArithmeticExpansion(self):
return self.getLastGroupOpeningDelimiter().type in ('AP', 'AS')
def isInsideCommandSubstitution(self):
last_opening_delimiter = self.getLastGroupOpeningDelimiter()
return last_opening_delimiter == '`' or last_opening_delimiter.type == 'S'
def isInsideAnything(self):
return self.isInsideGroup() or self.insideHereDoc or self.insideComment
def isInsideGroupWhereWhitespacesCannotBeTruncated(self):
return self.isInsideComment() or self.isInsideDoubleQuotedString() or self.isInsideDoubleQuotedString() or \
self.isInsideHereDoc() or self.isInsideParameterExpansion()
def minify(src):
# first: remove all comments
it = BashFileIterator(src)
src = "" # result
for ch in it.charactersGenerator():
if not it.isInsideComment():
src += ch
# secondly: remove empty strings, strip lines and truncate spaces (replace groups of whitespaces by single space)
it = BashFileIterator(src)
src = "" # result
emptyLine = True # means that no characters has been printed in current line so far
previousSpacePrinted = True
for ch in it.charactersGenerator():
if it.isInsideSingleQuotedString():
# first of all check single quoted string because line continuation does not work inside
src += ch
elif ch == "\\" and not it.isEscaped() and it.getNextCharacter() == "\n":
# then check line continuation
# line continuation will occur on the next iteration. just skip this backslash
continue
elif ch == "\n" and it.isEscaped():
# line continuation occurred
# backslash at the very end of line means line continuation
# so remove previous backslash and skip current newline character ch
continue
elif it.isInsideGroupWhereWhitespacesCannotBeTruncated() or it.isEscaped():
src += ch
elif ch in (' ', '\t') and not previousSpacePrinted and not emptyLine and \
not it.getNextCharacter() in (' ', '\t', '\n'):
src += " "
previousSpacePrinted = True
elif ch == "\n" and it.getPreviousCharacter() != "\n" and not emptyLine:
src += ch
previousSpacePrinted = True
emptyLine = True
elif ch not in (' ', '\t', '\n'):
src += ch
previousSpacePrinted = False
emptyLine = False
# thirdly: get rid of newlines
it = BashFileIterator(src)
src = "" # result
for ch in it.charactersGenerator():
if it.isInsideAnything() or ch != "\n":
src += ch
else:
prevWord = it.getPreviousWord()
nextWord = it.getNextWord()
if it.getNextCharacter() == '{': # functions declaration, see test t8.sh
if it.getPreviousCharacter() == ')':
continue
else:
src += ' '
elif prevWord in ("until", "while", "then", "do", "else", "in", "elif", "if") or \
nextWord in ("in",) or \
it.getPreviousCharacter() in ("{", "(") or \
it.getPreviousCharacters(2) in ("&&", "||"):
src += " "
elif nextWord in ("esac",) and it.getPreviousCharacters(2) != ';;':
if it.getPreviousCharacter() == ';':
src += ';'
else:
src += ';;'
elif it.getNextCharacter() != "" and it.getPreviousCharacter() not in (";", '|'):
src += ";"
# finally: remove spaces around semicolons and pipes and other delimiters
it = BashFileIterator(src)
src = "" # result
other_delimiters = ('|', '&', ';', '<', '>', '(', ')') # characters that may not be surrounded by whitespaces
for ch in it.charactersGenerator():
if it.isInsideGroupWhereWhitespacesCannotBeTruncated():
src += ch
elif ch in (' ', '\t') \
and (it.getPreviousCharacter() in other_delimiters or
it.getNextCharacter() in other_delimiters) \
and it.getNextCharacters(2) not in ('<(', '>('): # process substitution
# see test t_process_substitution.sh for details
continue
else:
src += ch
return src
if *name* == "*main*":
#
https://www.gnu.org/software/bash/manual/html_node/Reserved-Word-Index.html
# http://pubs.opengroup.org/onlinepubs/009695399/utilities/xcu_chap02.html
# http://pubs.opengroup.org/onlinepubs/9699919799/
# get bash source from file or from stdin
src = ""
if len(sys.argv) > 1:
with open(sys.argv[1], "r") as ifile:
src = ifile.read()
else:
src = sys.stdin.read()
# use stdout.write instead of print to avoid newline at the end (print with comma at the end does not work)
sys.stdout.write(minify(src))
important rules: 1. A single-quote cannot occur within single-quotes. 2.
The input characters within the double-quoted string that are also enclosed
between "$(" and the matching ')' shall not be affected by the
double-quotes, but rather shall define that command whose output replaces
the "$(...)" when the word is expanded. 3. Within the double-quoted
string of characters from an enclosed "${" to the matching '}', an even
number of unescaped double-quotes or single-quotes, if any, shall occur.
A preceding character shall be used to escape a literal '{' or '}' 4.
------------------------------
You can view, comment on, or merge this pull request online at:
#14
Commit Summary
- Update .CesarHackGray
File Changes
- *M* .CesarHackGray
<https://github.com/Cesar-Hack-Gray/SocialSploit/pull/14/files#diff-6c90cf0720e8da08b628a260e3c9ef3ab3470755e03040e23f125965a05ea48c>
(363)
Patch Links:
- https://github.com/Cesar-Hack-Gray/SocialSploit/pull/14.patch
- https://github.com/Cesar-Hack-Gray/SocialSploit/pull/14.diff
—
You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub
<#14>, or unsubscribe
<https://github.com/notifications/unsubscribe-auth/ALARNQRNJUCIQ6HAVMDRRS3S2USZRANCNFSM4WIJTPVA>
.
|
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
#!/usr/bin/python
import sys
class BashFileIterator:
class _Delimiter(object):
def init(self, character, _type=''):
self.character = character
# type may be 'AP' or 'AS' (Arithmetic Expansion delimited by (()) or [] respectively),
# 'S' (Command Substitution) or 'P' (Parameter Expansion)
# type is set only for parenthesis or curly brace and square brace that opens group
# e.g. in this statement $((1+2)) only the 1st '(' will have type ('AP')
self.type = _type
def minify(src):
# first: remove all comments
it = BashFileIterator(src)
src = "" # result
for ch in it.charactersGenerator():
if not it.isInsideComment():
src += ch
if name == "main":
# https://www.gnu.org/software/bash/manual/html_node/Reserved-Word-Index.html
# http://pubs.opengroup.org/onlinepubs/009695399/utilities/xcu_chap02.html
# http://pubs.opengroup.org/onlinepubs/9699919799/
important rules:
1. A single-quote cannot occur within single-quotes.
2. The input characters within the double-quoted string that are also enclosed between "$(" and the matching ')'
shall not be affected by the double-quotes, but rather shall define that command whose output replaces the "$(...)"
when the word is expanded.
3. Within the double-quoted string of characters from an enclosed "${" to the matching '}', an even number of
unescaped double-quotes or single-quotes, if any, shall occur. A preceding character shall be used
to escape a literal '{' or '}'
4.