Am seeing lots of examples of pytest (py.test) invocations that include the argument string '-xvvv'. I understand that -x means stop at first fail and a single v means verbose output. What do the extra v characters signify?
#hoefling, #Amit: Thanks! Increasing verbosity it is.
Related
As an example, double dash or two hyphens -- is used like so:
npm test -- --coverage
Running npm without the double dash flag does not run in coverage mode so it seems to append subsequent flags, is this correct? I couldn't find the documentation on this.
-- as an argument on its own is standardized across all UNIX commands: It means that further arguments should be treated as positional arguments, not options. See Guideline 10 in POSIX Utility Syntax Conventions.
To give you a non-NPM-based example, ls -- -l will look for a file named -l, because the -- specified that all subsequent arguments are positional.
In this context, it means that --coverage isn't an option to npm itself; presumably, then, it's subsequently read by the test subcommand. For a tool that were following the conventions properly this wouldn't be necessary, because Guideline 9 specifies that all options shall be given before any arguments (thus that in this context --coverage should be treated as an argument since it comes after the argument test); however, inasmuch as NPM is only partially following the guidelines, this is a foreseeable result.
(Long --option-style options are actually a GNU extension as a whole, so what we have here is a mismash of multiple parsing styles; such is life, unfortunately).
I've done some further digging; according to the docs for my node version -
"--" Indicates the end of node options. Pass the rest of the arguments to the script. If no script filename or eval/print script is supplied prior to this, then the next argument will be used as a script filename.
But, a simple script that contains -
console.log(`process.execArgv:${process.execArgv}`);
console.log(`process.argv:${process.argv}`);
behaves as -
>node --prof argv.js --myArg
process.execArgv:--prof
process.argv:C:\Program Files\nodejs\node.exe,C:\Dev\Web\QA_Web_POC\argv.js,--myArg
>node --prof argv.js -- --myArg
process.execArgv:--prof
process.argv:C:\Program Files\nodejs\node.exe,C:\Dev\Web\QA_Web_POC\argv.js,--, --myArg
>node argv.js --prof -- --myArg
process.execArgv:
process.argv:C:\Program Files\nodejs\node.exe,C:\Dev\Web\QA_Web_POC\argv.js,--prof,--,--myArg
>node argv.js -- --prof --myArg
process.execArgv:
process.argv:C:\Program Files\nodejs\node.exe,C:\Dev\Web\QA_Web_POC\argv.js,--,--prof,--myArg
So, it seems there's a bug?
I have a shell script where I have a statement:
isPartial = $searchCurl| grep -Po '\"partialSearch\":(true|false)'|sed 's/\\\"partialSearch\\\"://'
now, if I just echo the RHS
$searchCurl| grep -Po '\"partialSearch\":(true|false)'|sed 's/\\\"partialSearch\\\"://'
it prints "partialSearch":true, but the variable isPartial doesn't get initialized .
Why is this happening and how can I fix it ?
Since the number of backslashes in your examples varies, it is not clear to me if the double quotes are already escaped in the input text. I’ll assume they are not, i.e. the input text looks something like:
sometext... "partialSearch":true ... sometext...
..bla bla bla... "partialsearch":false ...
and my examples below will work under this assumption.
There are a number of points to be made.
You seem to be trying to parse JSON input with regular expressions. While this could be acceptable for quick-and-dirty one-time jobs where you know the exact format of the data being processed, in general it is a very bad idea. You should use a JSON parser like jq.
You obviously have stored some bash code in the variable searchCurl. This is considered bad practice. Instead of searchCurl="... code ..." you should do function searchCurl () { ... code ... } and call searchCurl without prefixing it with a dollar sign. Variables are for values, functions are for code.
In most cases, if you are going to use sed, it’s better to use it for everything without invoking grep. Sometimes it can be simpler to have both. See below for an example.
To assign the output of a command to a variable, you have to use command substitution.
In short, if in your input text you have only one match of '"partialSearch":(true|false)', this is what you want:
isPartial=$(searchCurl|sed -rn 's/^.*"partialSearch":(true|false).*$/\1/p')
If you have more and the input text is one big line as I suppose, usage of grep -o might simplify the task of splitting the input into one match per line, so that
isPartial=$(searchCurl|grep -Po '"partialSearch":(true|false)'|sed -e 's/^.*://')
might be what you want (and in this case, isPartial will hold a space-separated list of true and false).
I was reading tcollector init.sh file here: https://github.com/OpenTSDB/tcollector/blob/master/rpm/initd.sh#L25
what does the dash mean in the line 25TCOLLECTOR=${TCOLLECTOR-/usr/local/tcollector/tcollector.py}?
(I originally thought it just assigns the path after the dash to TCOLLECTOR; however my tests show two different results:
if TCOLLECTOR has already been assigned a value, it will conserve that value
else TCOLLECTOR will have the value "/usr/local/tcollector/tcollector.py"
I also looked at the use of "-" but it's all about STDIN and STDOUT...I didn't get a clue of how they are related to my question.)
Thank you.
That's an example of parameter expansion; the general POSIX variety is documented here, and you can read about the Bash incarnation here.
Basically, the minus sign expansion does exactly what you described: ${anyVariable-anyExpression} expands to the value of $anyVariable if it is set, but if it's not set, then it expands to anyExpression.
The plus sign does exactly the opposite: ${anyVariable+anyExpression} expands to anyExpression if $anyVariable has a value, and to nothing (the empty string) if it is unset.
There are several other options as well.
I have a parse a command line argument in shell script as follows:
cmd --a=hello world good bye --b=this is bash script
I need the parse the arguments of "a" i.e "hello world ..." which are seperated by whitespace into an array.
i.e a_input() array should contain "hello", "world", "good" and "bye".
Similarly for "b" arguments as well.
I tried it as follows:
--a=*)
a_input={1:4}
a_input=$#
for var in $a_input
#keep parsing until next --b or other argument is seen
done
But the above method is crude. Any other work around. I cannot use getopts.
The simplest solution is to get your users to quote the arguments correctly in the first place.
Barring that you can manually loop until you get to the end of the arguments or hit the next --argument (but that means you can't include a word that starts with -- in your argument value... unless you also do valid-option testing on those in which you limit slightly fewer -- words).
Adding to Etan Reisners answer, which is absolutely correct:
I personally find bash a bit cumbersome, when array/string processing gets more complex, and if you really have the strange requirement, that the caller should not be required to use quotes, I would here write an intermediate script in, say, Ruby or Perl, which just collects the parameters in a proper way, wraps quoting around them, and passes them on to the script, which originally was supposed to be called - even if this costs an additional process.
For example, a Ruby One-Liner such as
system("your_bash_script here.sh '".(ARGV.join(' ').split(' --').select {|s| s.size>0 }.join("' '"))."'")
would do this sanitizing and then invoke your script.
I'm writing a simple command line gem.
The library that does the actual work was developed with rspec and so far that works.
I'm trying to test the command line portion with Aruba/Cucumber, but I've come across some strange behaviour.
Just to test this, I've got a the binary file to puts ARGV, and I've got test files in tmp/aruba
When I run bundle exec gem_name tmp/aruba/*.* I am presented with the list of shell expanded file names.
Now my features file has:
Given files to work on # I set up files in tmp/aruba in this step
When I run `gem_name *.*` # standard step
Then the output should contain "Wibble"
The last step is obviously going to fail, but it shows me a diff between what it expects and the actual output. Rather than seeing a list of shell expanded filenames, all I get is "*.*"
So I'm left in the position of having an app that actually works as expected, but I can't get the tests to pass. I could take the "." and generate the list of files from there, but then I'm writing extra production code just to get the app to work under test - which I don't think is the correct way to go about it. And all because shell expansion isn't happening.
If you look at my profile, you'll see that Ruby isn't my main bag, feel free to point me at any resources that I may have missed about this, but is this just me missing something, or expected behaviour that somebody knows how to work around?
After a little digging in the Aruba source I figured out that the When I run step ends up in a code block like this:
def run!(&block)
#process = ChildProcess.build(*shellwords(#cmd))
...
begin
#process.start
...
Further digging into ChildProcess ends up here:
def launch_process
...
begin
exec(*#args)
...
And therein lies the problem. exec does not do shell expansion when the argument list is split into multiple array elements:
If exec is given a single argument, that argument is
taken as a line that is subject to shell expansion before being
executed. If multiple arguments are given, the second and
subsequent arguments are passed as parameters to command with no
shell expansion.
However playing with shellwords a bit we find:
Shellwords.shellwords('gem_name *.*')
=> ["gem_name", "*.*"] # No good
Shellwords.shellwords('"gem_name *.*"')
=> ["gem_name *.*"] # Aha!
Therefore the solution might be as simple as:
When I run `"gem_name *.*"`
If that doesn't work then you are pretty much out of luck. I would suggest you expand the file names manually since you're not really testing shell expansion here - we know that works: you are testing multiple arguments.
Therefore you should instead do:
When I run `gem_name your_file1 your_file2 your_file3`