Using command-line arguments in J - argv

I know that ARGV represents the arguments. Can I type arguments after the filename in jqt.exe or does that only work in jconsole.exe. Executing the code regarding ARGV given in the J docs crashes J on my Win 10. An example would be welcome.
I tried out 0 ". > ,. 2 }. ARGV from an earlier question on SO, but am not sure how to make it work.

Both jqt and jconsole read the command line arguments and box them:
jqt script.ijs arg1 arg2
ARGV
┌───┬──────────┬────┬────┐
│jqt│script.ijs│arg1│arg2│
└───┴──────────┴────┴────┘
2}. ARGV
┌────┬────┐
│arg1│arg2│
└────┴────┘
] x =: > 3 { ARGV
arg2
example script:
$ cat script.ijs
x =: ". every 2 }. ARGV
echo +/ x
$ jqt script.ijs 1 2 3
6

Related

Is there a way to pass multiple argument as a single string in bash?

I'm running a program that takes variable numbers of arguments with the same flag. For example
myprogram -args 'var1' 'var2' 'var3' 'var4'
myprogram -args 'var5' 'var6'
I have to launch this program several times with different sets of arguments provided in a test.txt file.
arg1 arg2 arg3
arg5 arg6
arg7
arg8 arg9 arg9 arg10
The program must be inside its own script to request resources in our HPCC.
while read p; do
launchmyprogram.sh "$p"
done < test.txt
I know I can use var1=$1 syntax inside launchmyprogram.sh to collect and allocate the variables, but this cannot handle variable number of arguments, and I'd have to create a script for each line. Is there a way to create a script in bash that takes variable numbers of arguments?
Use arrays to store dynamically sized sequences of strings. Bash has two ways of reading input into an array:
readarray -t somearray turns lines of an entire input file into array elements.
read -a somearray turns tokens of a single line of input into array elements.
In this case you can use the latter. Here’s a runnable MWE:
myprogram() {
local -i i
echo "Got ${#} arguments."
for ((i = 1; i <= $#; ++i)); do
echo "Argument No. ${i} is '${!i}'."
done
}
while read -ra args; do
myprogram -args "${args[#]}"
done <<-INPUT
arg1 arg2 arg3
arg5 arg6
arg7
arg8 arg9 arg9 arg10
INPUT
That way the arguments from each line are kept separate, as the output suggests:
Got 4 arguments.
Argument No. 1 is '-args'.
Argument No. 2 is 'arg1'.
Argument No. 3 is 'arg2'.
Argument No. 4 is 'arg3'.
Got 3 arguments.
Argument No. 1 is '-args'.
Argument No. 2 is 'arg5'.
Argument No. 3 is 'arg6'.
Got 2 arguments.
Argument No. 1 is '-args'.
Argument No. 2 is 'arg7'.
Got 5 arguments.
Argument No. 1 is '-args'.
Argument No. 2 is 'arg8'.
Argument No. 3 is 'arg9'.
Argument No. 4 is 'arg9'.
Argument No. 5 is 'arg10'.
You can use $# to query the number of arguments passed to launchmyprogram.sh. Something like
if [ $# -eq 1 ]; then
echo "one argument"
elif [ $# -eq 2 ]; then
echo "two arguments"
elif [ $# -eq 3 ]; then
echo "three arguments"
else
echo "too many arguments"
exit 1
fi
All bash scripts take a variable number of arguments, your question is about how to access them. The simplest method is:
for arg; do
my-cmd "$arg"
done
This repeats my-cmd with each argument, individually. You can use this loop in launchmyprogram.sh. You can also put the relevant code in a function, and use just the function inside the loop.
Parsing arguments from a file is more complicated. If the arguments aren't quoted for the shell, and don't contain spaces or wildcard characters ([]?*), you could just unquote $p in your example. It will be split on white space in to multiple arguments.
In this case you could also just parse the whole file in launchmyprogram.txt:
for arg in $(<test.txt); do
my-cmd "$arg"
done
This basically is Andrej's answer, but to simplify and make it just a little more directly related to the structure of the question -
while read -ra p; do # read and parse line into an array
myprogram -args "${p[#]}" # pass elements as separate values
done < test.txt # after reading them in as one line

How to work with command line arguments in J

In J console mode if I type ARGV I get the full path of jqt.exe But when I try to pass some strings to a J script file I get 'syntax error' or 'domain error'. How does argument passing and retrieval or display work?
If you want to write to a file you would pass the information using
'string' 1:!2 'filepath/jscriptfile'
see https://www.jsoftware.com/help/dictionary/dx001.htm
if you want to pass an argument to a verb declared in a script, you would first have to load the script
load 'filepath/jscriptfile'
Then as long as the script contains verbs that have been assigned using =: so that the verb is not local to the script file, you would pass the string to the verb, which has now been loaded.
verb 'string'
An interaction with a script that just prints out its arguments:
$ cat args.ijs
#! /usr/bin/env j
exit echo each ARGV
$ ./args.ijs
j
./args.ijs
$ ./args.ijs 1 2 3
j
./args.ijs
1
2
3
$ ./args.ijs '1 2' 3
j
./args.ijs
1 2
3
ARGV is a list of the boxed arguments to the script. It works like any list of boxed literals, and if you're a domain error it's from some verb in your script that's given arguments it's not defined to handle. If you're getting a syntax error it's because there's something in your script with incorrect syntax. This is unrelated to ARGV as such.
Perhaps you're expecting numerical arguments to be numbers? Arguments are always delivered as strings. Here's a slightly more involved script with usage, that prints the sum of the factorials of its arguments:
#! /usr/bin/env j
sumfact =: [: +/ [: ! x:
3 : 0''
if. (#ARGV) > 2 do.
echo sumfact > 0&". each 2}.ARGV
exit 0
else.
echo 'usage: ', (1{::ARGV), ' <n1> [<n2> ... <nn>]'
exit 1
end.
)
As used:
$ ./sumfact.ijs
usage: ./sumfact.ijs <n1> [<n2> ... <nn>]
$ ./sumfact.ijs 0
1
$ ./sumfact.ijs 5
120
$ ./sumfact.ijs 5 5 5
360
$ ./sumfact.ijs 100
93326215443944152681699238856266700490715968264381621468592963895217599993229915608941463976156518286253697920827223758251185210916864000000000000000000000000
The text after #! isn't important; I use /usr/bin/env j because I have a j in my path that's the usual bin/jconsole of a J installation.

Positional Parameters in C-shell

I am unable to print positional parameters using this shell command: echo $1.
I am using it as following two commands:
% set hi how are you
% echo $1
Nothing get out of the command, but hi should be print.
In csh, you need to assign to the argv array:
> set argv=(hi how are you)
> echo $1
hi
Explanation:
argv is an array variable which contains the command line argument list (the 0th argument is name as the shell was invoked and the other start from 1th index). Variables $0 - $n also contain values of the arguments . So $argv[1] is the same as $1. To assign to an array variable, you can use either set arr=(value1 value2) or set arr[1] = value1.
set value1 value2 would work in bash, but csh is meant to be similar to the C language, therefore the argv array is used (read a little about C program command line arguments if you don't know why).
But in csh, this: set first second means assigning an empty (null) value to the variables first and second.

C Shell modulus operator

I know c shell is very unfriendly but I am stuck with it. So can someone help me with this should-be-a-easy syntax error ? I would like to use modulus operator in c shell. So the command is like this and it keeps giving me syntax error of expr command.
set aVAr =`expr $number * 2 % $frequency`
I found out I can type "expr 6 % 5 " and "expr 3 * 2". However, I can not use command as "expr 3 * 2 % 5 ". What's wrong with it ? I think CSH should be table to take three operands at the same time ? Thank you very much,
expr is a command, not part of csh. You must escape the * to prevent csh from trying to expand it, as in
set aVAr =`expr $number \* 2 % $frequency`

how to perform a basic arithmetics from unix csh/tcsh shell

Under windows, when I need to perform a basic calculations, I use a built-in calculator. Now I would like to find out what is the common way if you only have a shell.
Thanks
From this web page (for csh and derivatives, since you asked):
% # x = (354 - 128 + 52 * 5 / 3)
% echo Result is $x
Result is 174
and
% set y = (354 - 128 + 52 / 3)
% echo Result is $y
Result is 354 - 128 + 52 / 3
notice the different results.
Personally, I stick to /bin/sh and call awk or something (for maximal portability), or others have exhibited the bash approach.
You can use dc. Or bc.
There are many good solutions given here, but the 'classic' way to do arithmetic in the shell is with expr:
$ expr 1 + 1
2
expr has a sensible return value, so that it succeeds when the expression evaluates to a non-zero value allowing code (in a Bourne shell) like:
$ op="1 + 1"
$ if expr $op > /dev/null; then echo "$op is not zero"; fi
1 + 1 is not zero
or (if using a shell that supports arrays):
$ op=(8 \* 3)
$ if expr "${op[#]}" > /dev/null; then echo "${op[#]} is not zero"; fi
8 * 3 is not zero
Note that the if syntax in Bourne shells is completely different than in the csh family, so this is slightly less useful and you need to check against the value of #?.
Bash supports basic (integer only) arithmetic inside $(( )):
$ echo $(( 100 / 3 ))
33
$ myvar="56"
$ echo $(( $myvar + 12 ))
68
$ echo $(( $myvar - $myvar ))
0
$ myvar=$(( $myvar + 1 ))
$ echo $myvar
57
(example copied straight from the IBM link)
More in-depth discussion of bash arithmetic
And you can always use the python interpreter, it's normally included in linux distros.
http://docs.python.org/tutorial/introduction.html#using-python-as-a-calculator
$ python
Python 2.6.2 (r262:71605, Apr 14 2009, 22:40:02) [MSC v.1500 32 bit (Intel)]
Type "help", "copyright", "credits" or "license" for more information.
>>> 2+2
4
>>> # This is a comment
... 2+2
4
>>> 2+2 # and a comment on the same line as code
4
>>> (50-5*6)/4
5
>>> # Integer division returns the floor:
... 7/3
2
>>> 7/-3
-3
>>> # use float to get floating point results.
>>> 7/3.0
2.3333333333333335
The equal sign ('=') is used to assign a value to a variable. Afterwards, no result is displayed before the next interactive prompt:
>>> width = 20
>>> height = 5*9
>>> width * height
900
And of course there's the math module which should solve most of your calculator needs.
>>> import math
>>> math.pi
3.1415926535897931
>>> math.e
2.7182818284590451
>>> math.cos() # cosine
>>> math.sqrt()
>>> math.log()
>>> math.log10()
You can also use Perl easily where bc or expr are not powerful enough:
$ perl5.8 -e '$a=1+2; print "$a\n"'
3
Alternative option is to use the built in BC command

Resources