Guides/J Shell Script

From J Wiki
Jump to: navigation, search

A #! (hashbang) J shell script in Unix systems (Linux or OSX) is an executable text file with a first line that starts with #! and a path to jconsole. The jconsole engine is run with the name of the hashbang file as an argument so that it will be loaded by J.

The #! line is run as a normal J sentence so it must run without error or side effect. This is the case with #!/home/fred/j807/bin/jconsole, but #!/home/fred/j64-802/bin/jconsole will get an error because of the - character. The workaround is to create a link file that has no characters that cause problems.

Try the following:

  • create file sumsquares with 3 lines of text:
#!/home/fred/j807/bin/jconsole
echo +/*:0".>,.2}.ARGV
exit''
  • make it executable ( chmod +x ) and run it in the terminal:
./sumsquares 1 2 3 4 5

Use NB. to comment out the exit'' to stay in J.

The following loads profile, which loads the #! script, which echos the result on the console and leaves J running.

#!/home/fred/j807/bin/jconsole
load'strings'
echo 'abcXXXdef' rplc 'XXX';' insert '

The following is the same, except it exits J at the end.

#!/home/fred/j807/bin/jconsole
load'strings'
echo 'abcXXXdef' rplc 'XXX';' insert '
exit''

The following does not load profile and just loads the script:

#!/home/fred/j807/bin/jconsole -jprofile
...

Profile loads jconsole with the following definitions that are useful in #! J scripts:

name description
ARGV boxed list of jconsole, script name, and arguments
echo format and display output
getenv get value of environment variable
stdin read from standard input
stdout write to standard output
stderr write to standard error
exit exit J (arg is return code)

stdin is defined with stdout as its obverse (see the :. conjunction). When used with &. (under conjunction), as in foo&.stdin '', stdin is first called, reading all of standard input. That input is the argument to foo, and the result is passed to the inverse of stdin, which is stdout.

A verb which transforms a character list can be combined with the stdin verb with under to apply the transformation as a Unix filter. As an example we will create a Unix filter which reverses all the characters in a file. Rather than just using |. we'll use (|.@}: , {:) which reverses all but the last character, and appends the last character to it. For files which end in a newline, this reverses the file keeping that newline at the end. Define the #! J script reverse as follows:

#!/home/fred/j807/bin/jconsole
rev=. |.@}: , {:
rev&.stdin ''
exit''

If you wanted to do a complete reverse of a file which does not end in a newline you could do the following:

rev=. |.`(|.@}: , {:)@.(LF&=@{:)

echo uses 1!:2 to write to J output (file number 2) and formats and writes any J array. However, stdout and stderr must be given character lists, and writes them unaltered. In particular, echo 'a line' will write a trailing newline character whereas stdout 'a line' does not.