Shell commands within if-block of gnuplot - if-statement

I want to execute shell commands inside if-block of Gnuplot. I tried the following:
datatype = 'full'
if ( datatype eq 'full' ) {
# Run shell command
!echo 'full'
} else {
# Run different shell command
!echo 'not full'
}
However, this gives me the error "filename.plt" line xx: invalid command
FYI, I already know instead of !echo, I can use print to do the same thing. That's not the point. I want to use shell commands with the symbol ! within the if-block. Any help will be appreciated.

#choroba has given the correct solution: use the system("command") function instead of !command.
As to why this is necessary, in brief:
(1) The ! operator is interpreted as indicating a shell command only if it is the first token on a gnuplot input line. Otherwise it is interpreted as a logical NOT.
(2) Gnuplot bracketed clauses { lots of commands } are treated internally as a single long input line. This is an implementation detail that has changed over time. The safest general guideline is that a bracketed clause should not contain any syntax that is documented as acting on or affecting a single line of input. This includes # macro substitution, single-line if statements, and as you found, the ! operator.
(1+2) Therefor a ! inside a bracketed clause is not seen as being the first token, and is interpreted as a logical NOT operator instead.

Related

What is the best way to specify a wildcard or regex in a "test" statement in configure.ac?

I am writing a configure.ac script for gnu autotools. In my code I have some if test statements where I want to set flags based on the compiler name. My original test looked like this:
if test "x$NETCDF_FC" = xifort; then
but sometimes the compiler name is more complicated (e.g., mpifort, mpiifort, path prepended, etc...), and so I want to check if the string ifort is contained anywhere within the variable $NETCDF_FC.
As far as I can understand, to set up a comparison using a wildcard or regex, I cannot use test but instead need to use the double brackets [[ ]]. But when configure.ac is parsed by autoconf to create configure, square brackets are treated like quotes and so one level of them is stripped from the output. The only solution I could get to work is to use triple brackets in my configure.ac, like this:
if [[[ $NETCDF_FC =~ ifort ]]]; then
Am I doing this correctly? Would this be considered best practices for configure.ac or is there another way?
Use a case statement. Either directly as shell code:
case "$NETCDF_FC" in
*ifort*)
do_whatever
;;
*)
do_something_else
;;
esac
or as m4sh code:
AS_CASE([$NETCDF_FC],
[*ifort*], [do_whatever],
[do_something_else])
I would not want to rely on a shell capable of interpreting [[ ]] or [[[ ]]] being present at configure runtime (you need to escape those a bit with [] to have the double or triple brackets make it into configure).
If you need a character class within a case pattern (such as e.g. *[a-z]ifort*), I would advise you to check the generated configure file for the case statement patterns which actually end up being used until you have enough [] quotes added around the pattern in the source configure.ac file.
Note that the explicit case statements often contain # ( shell comments at the end of the lines directly before the ) patterns to avoid editors becoming confused about non-matching opening/closing parentheses.

Zsh - How can I compare a variable whose name begin with '~' symbol against a 'if' statement?

I would like to automate zsh's installation and configuration and I am currently unable to check out either a file whose name begin with '~' exists and is not empty.
zsh_rcfile='~/.zshrc'
set -- $zsh_rcfile
if [ -s "${zsh_rcfile}" ]; then
printf "Zsh is already configured."
fi
When I execute the script into the terminal, no error is returned but no output is produced as well.
I tried to hard code the pathname, or use it without the curly braces but the result is the same.
I also tried not using the set command (which prevent nasty surprises with empty names or names beginning with a dash).
The 'if' statement would work without the tilde symbol (i.e. ~) but it would account for an inferior solution as I need to automate other processes required to cross the system tree (and not just the 'home' partition).
Does anyone accept to help me achieving the comparison against a path beginning with '~'?
N.B.: I'm using zsh 5.7.1 (x86_64-debian-linux-gnu).
Tilde expansion isn't performed on the result of a parameter expansion. You want to leave the ~ unquoted so that it is expanded when you define the parameter.
% zsh_rcfile='~/.zshrc'
% print $zsh_rcfile
~/.zshrc
% zsh_rcfile=~/.zshrc
% print $zsh_rcfile
/Users/<user>/.zshrc
The -s operator returns false if the file doesn't exist in the first place (which makes sense, since a nonexistent file is trivially empty).
-s file
true if file exists and has size greater than zero.

Detecting semicolon as command line argument in linux

I am trying to run a C++ application where I am passing some command line arguments to it as follows:
./startServer -ip 10.78.242.4 tcpip{ldap=no;port=2435}
The application is getting crashed because it is not able to get the correct port. Searching over the web, I found that ";" is treated an end of command character (Semicolon on command line in linux) so everything after that is getting ignored. I also understand the putting it inside the quotes will work fine. However, I do not want to force this restriction of putting the arguments in the quotes on the users. So, I want to know is there a way I can process the ";" character with the argv array?
The semicolon separates two commands so your command line is equivalent to
./startServer -ip 10.78.242.4 tcpip{ldap=no
port=2435}
Your application will never know anything about either the semi colon or the second command, these will be completely handled by the shell. You need to escape the colon with a back slash or enclose it in quotes. Other characters which may cause similar issues include: $,\-#`'":*?()&|
Complex strings are much easier to pass either from a file or through stdin.
You need to quote not only the ; but in the general case also the { and }:
./startServer -ip 10.78.242.4 'tcpip{ldap=no;port=2435}'
If your users are required to type in that complicated last argument, then they can also be made to quote it.

Finding and modifying function definitions (C++) via bash-script

Currently I am working on a fairly large project. In order to increase the quality of our code, we decided to enforce the treatement of return values (Error Codes) for every function. GCC supports a warning concerning the return value of a function, however the function definition has to be preceeded by the following flag.
static __attribute__((warn_unused_result)) ErrorCode test() { /* code goes here */ }
I want to implement a bashscript that parses the entire source code and issues a warning in case the
__attribute__((warn_unused_result))
is missing.
Note that all functions that require this kind of modification return a type called ErrorCode.
Do you think this is possible via a bash script ?
Maybe you can use sed with regular expressions. The following worked for me on a couple of test files I tried:
sed -r "s/ErrorCode\s+\w+\s*(.*)\s*\{/__attribute__((warn_unused_result)) \0/g" test.cpp
If you're not familiar with regex, the pattern basically translates into:
ErrorCode, some whitespace, some alphanumerics (function name), maybe some whitespace, open parenthesis, anything (arguments), close parenthesis, maybe some whitespace, open curly brace.
If this pattern is found, it is prefixed by __attribute__((warn_unused_result)). Note that this only works if you are putting the open curly brace always in the same line as the arguments and you don't have line breaks in your function declarations.
An easy way I could imagine is via ctags. You create a tag file over all your source code, and then parse the tags file. However, I'm not quite sure about the format of the tags file. The variant I'm using here (Exuberant Ctags 5.8) seems to put an "f" in the fourth column, if the tag represents a function. So in this case I would use awk to filter all tags that represent functions, and then grep to throw away all lines without __attribute__((warn_unused_result)).
So, in a nutshell, first you do
$ ctags **/*.c
This creates a file called "tags" in the current directory. The command might also be ctags-exuberant, depending on your variant. The **/*.c is a glob pattern that might work in your shell - if it doesn't, you have to supply your source files in another way (look at the ctagsoptions).
Then you filter the funktions:
$ cat tags | awk -F '\t' '$4 == "f" {print $0}' | grep -v "__attribute__((warn_unused_result))"
No, it is not possible in the general case. The C++ grammar is the most complex of all the languages I know of, and C++ is not parsable via regular expressions in the general case. You might succeed if you limit yourself to a very narrow set of uses, but I am not sure how feasible it is in your case.
I also do not think the excersise is worth the effort, since sometimes ignoring the result of the function is an OK thing.

Regular Expression TCL using procedure

I am a novice TCL programmer. Here I go - My 1st post with stackoverflow forum.
I would like to write a regular expression that matches any & only the strings starts with character A and ends with B. Whatever the characters coming inbetween should be displayed. For instance AXIOMB as an input from the user which starts with A & end with character B.
Here is my try
regexp { (^A([C-Z]+)B$)}
Thank you
You're very close:
set stringToTest "AXIOMB"
set match [regexp {^A([C-Z]*)B$} $stringToTest -> substring]
if {$match} {
puts "The middle was $substring"
}
(The -> is actually an unusual variable name. But here I'm using that symbol because it looks better than using the otherwise-equivalent someRandomDummyVariable. :-))
If you're seeking to get the string to test from the command line or the console, here's how:
Command line arguments (without the name of the Tcl interpreter or the script) are presented as a list in the global argv list variable. The first one is thus [lindex $::argv 0].
A line can be read from the console via the gets command.
set line [gets stdin]; # you can use other channel names too, of course
Note that, unlike in C, gets in Tcl is strongly defended against buffer overflows and the (almost) full power of scanf() is about equivalent to scan [gets stdin] ... (except for some formats excluded for security reasons).