BATsh
view release on metacpan or search on metacpan
$(( arithmetic )) -- full C-style operator set:
+ - * / % ** (** right-assoc; / % truncate toward zero)
== != < <= > >= && || ! (results 0/1)
& ^ | ~ << >> (bitwise; ~ is signed)
= += -= *= /= %= <<= >>= &= ^= |= (write back to the variable)
++ -- (prefix and postfix), ?: (ternary), comma
0xNN hex and 0NN octal literals, $1..$9 inside
$( command ) and `command` (command substitution, nested)
cmd1 | cmd2 [| cmd3 ...] (pipeline via temporary file)
cmd1 && cmd2, cmd1 || cmd2, cmd1 ; cmd2 (compound commands)
> >> < 2> 2>> 2>&1 1>&2 (I/O redirection)
name() { ... }, function name { ... } (function definitions)
$VAR, ${VAR}, $1..$9, $@, $*, $#, $?, $$, $0
${VAR:-default}, ${VAR:=default}, ${VAR:+alt}
${VAR%pat}, ${VAR%%pat} -- shortest/longest suffix removal
${VAR#pat}, ${VAR##pat} -- shortest/longest prefix removal
${VAR/pat/rep}, ${VAR//pat/rep} -- first/all substitution
${VAR^^}, ${VAR^}, ${VAR,,}, ${VAR,} -- case conversion
${VAR:N:L}, ${VAR:N} -- substring
${#VAR} -- string length
arr=(a b c), arr+=(d e), arr[i]=v, arr[i]+=v -- indexed arrays
declare -a arr, declare -A map, typeset ... -- array declaration
map=([k]=v ...), map[k]=v -- associative arrays
${arr[i]}, ${map[key]}, $arr (== ${arr[0]}) -- element access
${arr[@]}, ${arr[*]}, ${#arr[@]}, ${#arr[i]}, ${!arr[@]}
unset arr, unset arr[i]
source / . file
{a,b,c}, {1..5}, {a..e}[..step] -- brace expansion
shopt -s/-u extglob; ?(),*(),+(),@(),!() -- extended pattern
matching in case patterns and ${VAR%pat}-family patterns
cmd <<< word -- here-string
<(cmd), >(cmd) -- process substitution via temp file
select VAR in list; do ... done -- menu loop
alias name=value, alias, unalias
exec cmd, exec > file ...
( cmd1; cmd2 ) -- subshell command group, isolated scope
ENCODING (CP932 / Shift_JIS SUPPORT)
Scripts written in CP932 -- the ANSI encoding of Japanese Windows -- run
correctly as of version 0.07, including the notorious "dame-moji" whose
second byte collides with an ASCII shell metacharacter:
SO (0x83 0x5C) trail byte = backslash
HYOU (0x95 0x5C) trail byte = backslash
PO (0x83 0x7C) trail byte = pipe
CHI (0x83 0x60) trail byte = backtick
DA (0x83 0x5E) trail byte = caret (the cmd.exe escape)
The encoding is auto-detected by default: a non-UTF-8 source containing
bytes above 0x7F is treated as CP932. Pure-ASCII and UTF-8 scripts are
unaffected. Explicit selection:
BATsh->run($file, encoding => 'cp932'); # per run
BATsh->set_encoding('cp932'); # for the process
set BATSH_ENCODING=cp932 # environment variable
perl lib/BATsh.pm --encoding=cp932 script.batsh
Supported names: cp932 (sjis), gbk (cp936), uhc (cp949), big5 (cp950),
utf8, none, auto. Under an active DBCS encoding the substring and length
operators "${#VAR}", "${VAR:N:L}" and "%VAR:~n,m%" count characters
rather than bytes. A UTF-8 BOM on the first line is stripped. See
BATsh::MB for the mechanism.
EXIT STATUS
"run", "run_string" and "run_lines" return the script's final exit
status as an integer: the argument of SH "exit N" or CMD "EXIT [/B] N"
if one was executed, otherwise the status of the last command. "EXIT"
with no code keeps the current "ERRORLEVEL" (so "false" then "EXIT /B"
returns 1). The same value is available afterwards as
"BATsh->last_status".
At every CMD/SH section boundary the status is mirrored in both
directions, so an SH failure is immediately visible as "%ERRORLEVEL%"
(and "IF ERRORLEVEL n") in the following CMD section, and a CMD failure
is visible as $? in the following SH section.
"BATsh->main(@ARGV)" implements the command-line interface used by the
modulino ("perl lib/BATsh.pm ...") and by bin/batsh.pl (installed as
"batsh.pl"; on Windows MakeMaker's pl2bat also provides "batsh"):
"--help", "--version", "-e 'source'", a script filename, or "-" to read
the script from STDIN. With a script filename or with "-", the remaining
arguments become %1..%9 / $1..$9. With "-e" they do not: every remaining
argument is joined with newlines onto the inline source, so "-e 'echo
one' 'echo two'" runs a two-line script. The modulino calls
"exit(BATsh->main(@ARGV))", so the OS-level exit code of the process is
the script's own status. In the REPL, "exit N" / "EXIT N" ends the
session.
REQUIREMENTS
Perl 5.005_03 or later. Core modules only. No external shell required.
BUGS AND LIMITATIONS
Commands that are not built in -- "FINDSTR", "SORT", "MORE", "CHOICE",
"TIMEOUT", "XCOPY", "ROBOCOPY" and the like in CMD mode, and any
non-builtin program in SH mode -- are not reimplemented in Perl. They
are invoked as external programs (via Perl's "system"), so they work
only where the host operating system provides the corresponding
executable (e.g. FINDSTR.EXE on Windows). This is by design: only the
built-in command set is guaranteed to run identically on every platform.
The built-in CMD interpreter does not implement:
* "FOR /F" with "usebackq" backtick-quoted commands on Windows (the
"cmd /c" subprocess path is untested on Windows).
Variable substring "%VAR:~n,m%" / "%VAR:~n%" / "%VAR:~-n%" /
"%VAR:~n,-m%" and in-place substitution "%VAR:str1=str2%" /
"%VAR:*str1=str2%" are now supported as of version 0.05 (see
BATsh::Env).
Dynamic pseudo-variables "%DATE%" (YYYY-MM-DD), "%TIME%" (HH:MM:SS.cc),
"%CD%" (current directory), "%RANDOM%" (0-32767), "%ERRORLEVEL%", and
"%CMDCMDLINE%" are now supported as of version 0.05.
Indexed and associative arrays -- "arr=(a b c)", "arr+=(...)",
"arr[i]=v", "declare -A map", "map=([k]=v ...)", "${arr[i]}",
"${arr[@]}", "${#arr[@]}", "${!arr[@]}", and "unset arr[i]" -- are now
supported as of version 0.06 (see BATsh::SH). Element ordering for
"${arr[@]}" is ascending numeric index for indexed arrays and sorted key
order for associative arrays (bash leaves the latter unspecified);
"${arr[@]}" word-splits to one item per element in "for" lists.
( run in 2.747 seconds using v1.01-cache-2.11-cpan-364913b4093 )