I'm writing a little tool which uses an existing framework via import.
The part I'm using is:
def exec_command(self, command, timeout=60, mode=cli.CLIMode.UNDEF,
output_expected=None, error_expected=False, prompt=None):
"""Executes the given command.
This method handles detecting simple boolean conditions such as
the presence of output or errors.
:param command: command to execute, newline appended automatically
:param timeout: maximum time, in seconds, to wait for the command to
finish. 0 to wait forever.
:param mode: mode to enter before running the command. The default
is :func:`default_mode`. To skip this step and execute directly
in the cli's current mode, explicitly set this parameter to None.
:param output_expected: If not None, indicates whether output is
expected (True) or no output is expected (False).
If the opposite occurs, raise UnexpectedOutput. Default is None.
:type output_expected: bool or None
:param error_expected: If true, cli error output (with a leading '%')
is expected and will be returned as regular output instead of
raising a CLIError. Default is False, and error_expected always
overrides output_expected.
:type error_expected: bool
:param prompt: Prompt regex for matching unusual prompts. This should
almost never be used as the ``mode`` parameter automatically
handles all typical cases. This parameter is for unusual
situations like the install config wizard.
:return: output of the command, minus the command itself.
:raises CmdlineTimeout: on timeout
:raises CLIError: if the output matches the cli's error format, and
error output was not expected.
:raises UnexpectedOutput: if output occurs when no output was
expected, or no output occurs when output was expected
"""
if output_expected is not None and type(output_expected) is not bool:
raise TypeError("exec_command: output_expected requires a boolean "
"value or None")
if mode is cli.CLIMode.UNDEF:
mode = self.default_mode
if mode is not None:
self.enter_mode(mode)
self._log.debug('Executing cmd "%s"' % command)
if prompt is None:
prompt = self._prompt
(output, match_res) = self._send_line_and_wait(command,
prompt,
timeout=timeout)
# CLI adds on escape chars and such sometimes and the result is that
# some part of the command that was entered shows up as an extra
# initial line of output. Strip off that initial line.
output = '\n'.join(output.splitlines()[1:])
if output and (re.match(self.CLI_ERROR_PROMPT, output)):
if error_expected:
# Skip output_expected processing entirely.
return output
else:
try:
mode = self.current_cli_mode()
except exceptions.UnknownCLIMode:
mode = '<unrecognized>'
raise exceptions.CLIError(command, output=output, mode=mode)
if ((output_expected is not None) and (bool(output) !=
bool(output_expected))):
raise exceptions.UnexpectedOutput(command=command,
output=output,
expected_output=output_expected)
return output
I'm using in my script:
print sh.cli.exec_command(command, mode="enable")
this works perfectly fine. The tool is logging into the appliance, executing the command. According to the framework it's "return" is ":return: output of the command, minus the command itself." This also works fine, when the command is executed, I get:
Generated dump sysdump-csh-20150320-140445.tgz
Perfect! For the next step, I need the name of the dump created, i.e. the return string without the "Generated dump " text.
Now I'm struggling in parsing that into a new variable I can use to e.g. download the generated dump and delete it afterwards, etc.
s = "Generated dump sysdump-csh-20150320-140445.tgz"
print s.split()[-1]
Yields
"sysdump-csh-20150320-140445.tgz"
This is just parsing by splitting on whitespace. Every parsing decision depends on some assumptions. This one depends on the assumption that the file name you want will be contiguous (no internal spaces), and the the last item on a whitespace-split list.
Martijn Pieters beat me to the improved formulation of this:
s.split(None, 2)[-1]
Or even better:
s.strip().split(None, 2)[-1]
This is the best because it doesn't also assume that the file name is contiguous. The .strip() also removes the assumption that there are no trailing spaces.
Keep in mind that whatever simple parsing strategy you choose, it's always dependent on assumptions. Even with the improved formulation here, for instance, we still assume the file name is the last item on the line. If the program producing this line were updated to "Generated dump sysdump-csh-20150320-140445.tgz on March 20, 2015." say, we'd have to finagle it yet another way.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With