diff --git a/CHANGELOG.md b/CHANGELOG.md index 5ae180d6..021f2968 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,13 +15,14 @@ - [csharp] recognise functions with nullable results ### Changed -- Simplified catalog.xml. +- Simplified catalog.xml. - Use new xsd schema for catalog.xml. - Common.jar rename to common.zip - reformat proto.hrc and included files; changed namespace. - Tweak visual.hrd xml CData markup - remove obsolete from visual-rgb.hrd - [groovy] add .gradle as groovy +- Use the new shell-posix schema for shell scripts by default ### Added - New package type of base - all packed. Hrc and hrd files in one archive. Directory 'auto' not in archive. @@ -37,6 +38,8 @@ - [csharp] support C# 11 raw strings - [cpp] add support for C++11 string literals - [asm] add new registers, blocks. New masks for filenames and firstline +- [shell-posix] add a new schema for POSIX shell with block structures and error checking +- [shell-bash] add a new schema for bash script based on shell-posix ## [1.2.0] - 2021-09-12 diff --git a/hrc/hrc/proto.hrc b/hrc/hrc/proto.hrc index b4dff6e7..f8f04669 100644 --- a/hrc/hrc/proto.hrc +++ b/hrc/hrc/proto.hrc @@ -591,11 +591,23 @@ + /^\#(!\s*.+sh\b)/ + + + /\.(sh|spec)$/i /^PKGBUILD$/i - /\.(bash_|z)?profile/ - /\.(ba|k|z)?shrc/ - /^\#(!\s*.+sh\b)/ + /\.z?profile/ + /\.(k|z)?shrc/ + /^\#(!\s*.+sh\b)/ + + + + /\.sh$/i + /\.bash$/i + /\.bash_profile/ + /\.bashrc/ + /^\#!(\s*.+bash\b)/ diff --git a/hrc/hrc/scripts/shell-bash.hrc b/hrc/hrc/scripts/shell-bash.hrc new file mode 100644 index 00000000..bde4024f --- /dev/null +++ b/hrc/hrc/scripts/shell-bash.hrc @@ -0,0 +1,698 @@ + + + + + + + Shell Scripts (bash) + + Based on: + https://www.gnu.org/software/bash/manual/bash.html + This is Edition 5.2, last updated 19 September 2022 + + Notes: + - nested here-docs are not supported. + + Home: https://github.com/chpock/ck.colorer-schemes + Send requests there for bug fixes and features. + + + ]]> + + + + + /\.sh$/i + /\.bash$/i + /^\#(!\s*.+bash\b)/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/hrc/hrc/scripts/shell-posix.hrc b/hrc/hrc/scripts/shell-posix.hrc new file mode 100644 index 00000000..136935e2 --- /dev/null +++ b/hrc/hrc/scripts/shell-posix.hrc @@ -0,0 +1,645 @@ + + + + + + + Shell Scripts (POSIX) + + Based on: + IEEE Std 1003.1-2008 + https://pubs.opengroup.org/onlinepubs/9699919799/utilities/toc.html + + Notes: + - nested here-docs are not supported. + + Home: https://github.com/chpock/ck.colorer-schemes + Send requests there for bug fixes and features. + + + ]]> + + + + + /\.(sh|spec)$/i + /^PKGBUILD$/i + /^\#(!\s*.+sh\b)/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/hrc/test/_valid/other/test.sh.html b/hrc/test/_valid/other/test.sh.html deleted file mode 100644 index 5f2d1966..00000000 --- a/hrc/test/_valid/other/test.sh.html +++ /dev/null @@ -1,9 +0,0 @@ -0: -1: #!/bin/sh -2: (cd x; y/a-b.sh) -3: -4: echo ${#aoeu[@]} -5: -6: DATE=`date` -7: echo $DATE -8: diff --git a/hrc/test/_valid/shell/shell-bash-spec.bash.html b/hrc/test/_valid/shell/shell-bash-spec.bash.html new file mode 100644 index 00000000..facdc946 --- /dev/null +++ b/hrc/test/_valid/shell/shell-bash-spec.bash.html @@ -0,0 +1,459 @@ + 0: #!/usr/bin/env bash + 1: + 2: # 3.1.2.4 ANSI-C Quoting + 3: + 4: $'\nfoo\e' + 5: A=$'\\\'\"\?no special meaning' + 6: CDPATH=$'octal \1 \12 \123 foo' $'octal error \9 \19 \181 foo' + 7: command ${CDPATH%$'test\rtest'} `in backquote $'test\1test'` + 8: ( in subshell $'\1' ) + 9: { in group $'1'; } + 10: command $'hex \x1 \x1a \xFFnospecial meaning' + 11: A=$(foo $'unicode \u1 \uF1 \uFFA \udeadno special meaning') + 12: $'unicode \U1 \UF1 \UFFA \Udead \UDEAD1 \U12345 \U123456 \U1234567 \U12345678no special meaning' + 13: $'control-x \cx no cpecial meaning' + 14: + 15: # 3.1.2.5 Locale-Specific Translation + 16: + 17: $"some message" + 18: A=$"some message $VAR inside" + 19: CDPATH=$"msg $'ansi-c\\here\r'" + 20: command ${CDPATH%$"msg $(command)"} + 21: ( in subshell $"msg" ) + 22: { in group $"msg"; } + 23: A=$(foo $"something $'ansi-c\t\\' ${CDPATH#$"msg"}") `in bq $"some\$th\\i\ng"` + 24: + 25: # 3.2.5.1 Looping Constructs + 26: # for (( expr1 ; expr2 ; expr3 )) ; do commands ; done + 27: + 28: for (( i = 0; $i < $VAR; i++ )); do + 29: cmd + 30: done + 31: + 32: for (( i = 0; i < $VAR; i++ )); do + 33: cmd + 34: done + 35: + 36: for (( i = 0; $i < '$NO_VAR'; i = $i + $'ansi-c' )) + 37: do + 38: cmd + 39: done + 40: + 41: for (( i = "123"; $i < ${CDPATH}; i = $i / 100 )); do V1=456 command here; done + 42: for ((;;)); do V1=456 command here; done + 43: + 44: # 3.2.5.2 Conditional Constructs + 45: + 46: # select + 47: + 48: select var in $VAR; do + 49: + 50: done + 51: + 52: select var in; do done + 53: + 54: select VAR in "BLA" "FOO" "BAR"; do; done + 55: + 56: select VAR; do + 57: command + 58: if [ -n "$FOO" ]; then + 59: something + 60: select VAR; do + 61: done + 62: fi + 63: select VAR; do + 64: select VAR; do + 65: done + 66: done + 67: done + 68: + 69: select IFS in; do done # POSIX special variable + 70: select CDPATH in; do done # Bash special variable + 71: + 72: ( select VAR; do done ) + 73: { select VAR; do done; } + 74: + 75: + 76: # (( ... )) + 77: + 78: (( "asd" '123' $'\r\t123' $"foo" 1 )) # test strings / numbers + 79: (( $(V1=1 command) `command` )) # evaluations + 80: (( \$ \" \' \$ )) # escapes + 81: (( $VAR $IFS $CDPATH )) # variables + 82: (( ${VAR%10} ${IFS#10} ${CDPATH%10} )) # parameter expansion + 83: (( i++ i-- ++IFS --CDPATH )) # increment / decrement + 84: (( 1 + 1 - 2 ! 1 ~ 3 ** 3 * 4 / 5 % -6 >> 10 << 20 )) # operations + 85: (( 1 <= 2 >= 4 < 1 > 4 == 5 != 4 & 1 ^ 5 | 8 && 10 || 20 ? 30 : 2 )) # operations + 86: (( a = 1 || w *= 1 || IFS /= 10 || CDPATH %= 10 || x += 10 || y -= 10 )) # assignment + 87: (( a <<= 10 || b >>= 30 || c &= 1 || f |= 40 )) # assignment + 88: + 89: (( 0174 + 0$VAR + 8#123 + 09874 + 8#845 )) # octal + octal var + bad octal numbers + 90: (( 0x12F + 0XDeaDBeEf111 + 0x$VAR + 16#411Ab + 0x1Z23 + 16#123K )) # hex + hex var + bad hex numbers + 91: (( 3#10 + 10#$VAR + 44#50 + 65#567 )) # any base + wrong base (65+) + 92: (( 2#45 + 10#45A )) # bad bin/dec bases + 93: + 94: # [[ ... ]] + 95: + 96: [[ a -f e || -f /bla || -o fofofof || -v varname || -R varname && -z "$STRING" ]] + 97: [[ 1 > 2 ]] + 98: [[ "asd" '123' $'\r\t123' $"foo" 1 ]] # test strings / numbers + 99: [[ $(V1=1 command) `command` ]] # evaluations +100: [[ \$ \" \' \$ ]] # escapes +101: [[ $VAR $IFS $CDPATH ]] # variables +102: [[ ${VAR%10} ${IFS#10} ${CDPATH%10} ]] # parameter expansion +103: [[ $fffj =~ [[:space:]]*(a)?b ]] +104: [[ $line =~ ^"initial string" ]] +105: [[ $line =~ "^initial string" ]] +106: pattern='[[:space:]]*(a)?b' +107: [[ $line =~ $pattern ]] +108: [[ $line =~ $CDPATH ]] # special variable +109: [[ 'Hello World' =~ Hello ]] +110: [[ $digit =~ [0-9] ]] +111: [[ $REPLY =~ ^[0-9]+$ ]] # special variable +112: [[ "$email" =~ ^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+.[A-Za-z]{2,4}$ ]] +113: [[ $ip =~ ^[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}$ ]] +114: +115: # 3.2.6 Coprocesses +116: +117: coproc CDPATH { +118: select far in; do +119: done +120: } 2>/dev/null +121: +122: coproc name_as_variable { V=1 command here; } 2>/dev/null 1<foo +123: +124: coproc command here 1>/dev/null +125: +126: coproc name_as_var { +127: V=1 command here +128: } +129: +130: coproc { +131: V1=1 command here +132: } +133: +134: # 3.3 Shell Functions +135: +136: func-name () command here 2>/dev/null +137: +138: func%name () { +139: command here +140: } 2>/dev/null +141: +142: func-name () { command here; } +143: +144: ,func-name-comma () { command here; } +145: +146: function fu1[nc]name command here 1>/dev/null +147: +148: function f-un[c () command here +149: +150: function f123 () { +151: command here +152: } +153: +154: function func-name { command here; } +155: +156: function -error here; +157: +158: # 3.5.3 Shell Parameter Expansion +159: +160: ${A:-word} ${BASH:-word} +161: ${A:=word} ${BASH:=word} +162: ${A:?word} ${BASH:?word} +163: ${A:+word} ${BASH:+word} +164: +165: ${A:0} ${A:0:10} ${A: -1} ${A: -1:-10} ${BASH:0} ${BASH:0:10} ${BASH: -1} ${BASH: -1:-10} +166: ${@:7} ${@:1:2} ${*:1} ${*:1:2} +167: ${A:$(( ${#B} + 10 )):$(command here)} ${A:"10":$'\r\t10'} +168: +169: ${!prefix*} ${!prefix@} ${!1@} +170: +171: ${!name[@]} ${!name[*]} +172: ${!A} ${!BASH} ${!1} ${!@} +173: +174: ${#A} ${#BASH} ${#*} ${#@} +175: ${A#word} ${BASH#word} ${A##word} ${BASH##word} +176: ${A%word} ${BASH%word} ${A%%word} ${BASH%%word} +177: +178: ${A/pat/str} ${BASH/pat/str} ${A//pat/str} ${BASH//pat/str} +179: ${A/#pat/str} ${BASH/#pat/str} ${A/%pat/str} ${BASH/%pat/str} +180: ${A/$(command)/`test`"dbl"$'ansi'} +181: +182: " ${A/pat/str} ${A/$(command)/`test`"dbl"$'ansi'} " # <- in double quoted strings +183: +184: ${A^pat} ${BASH^pat} ${A^^pat} ${BASH^^pat} +185: ${A,pat} ${BASH,pat} ${A,,pat} ${BASH,,pat} +186: ${A^$(command here)} ${BASH,,`test`"sdfasdf"$'\r\t\e'} +187: +188: ${A@U} ${A@u} ${A@L} ${A@Q} ${A@E} ${A@P} ${A@A} ${A@K} ${A@a} ${A@k} +189: ${BASH@U} ${BASH@u} ${BASH@L} ${BASH@Q} ${BASH@E} ${BASH@P} ${BASH@A} ${BASH@K} ${BASH@a} ${BASH@k} +190: +191: for i in; do +192: "'${M:$i:1}" # <- test in for loop +193: done +194: +195: # 5.1 Bourne Shell Variables +196: +197: $CDPATH $HOME $IFS $MAIL $MAILPATH $OPTARG $OPTIND $PATH $PS1 $PS2 +198: +199: ${#CDPATH} +200: +201: CDPATH=1 CDPATH=somestring +202: +203: # 3.5.6 Process Substitution +204: +205: command here <(V=1 command here) >(V=1 command here) +206: +207: command here < <(V=1 command here) +208: +209: # 3.6 Redirections +210: +211: ls > dirlist 2>&1 +212: ls 2>&1 > dirlist +213: +214: # 3.6.1 Redirecting Input +215: +216: command < test < $VAR +217: command 2< test 1<$CDPATH +218: +219: # 3.6.2 Redirecting Output +220: +221: command >test >$VAR +222: command >|test >|$VAR +223: command 1>test 2>$VAR +224: command 1>|test 0>|$VAR +225: +226: # 3.6.3 Appending Redirected Output +227: +228: command >>test >>$VAR +229: command 2>>test 2>>$VAR +230: +231: # 3.6.4 Redirecting Standard Output and Standard Error +232: +233: command &>test >&test +234: command >test 2>&1 +235: +236: # 3.6.5 Appending Standard Output and Standard Error +237: +238: command &>>test +239: +240: # 3.6.7 Here Strings +241: +242: command <<< word +243: command <<< $VAR +244: command <<< $(V=1 command here) +245: command 1<<< word +246: command 1<<< "string"$'ansi''single' +247: command <<< "HERE STRING" +248: +249: for i in; do +250: if bla; then +251: while read -r; do +252: done <<< "HERE STRING" +253: fi +254: done +255: +256: # 3.6.8 Duplicating File Descriptors +257: +258: command <&1 +259: command 1<&1 +260: command 1<&$VAR +261: command 1<&- +262: command >&1 +263: command 2>&3 +264: command 1>&$VAR +265: command 1>&- +266: +267: # 3.6.9 Moving File Descriptors +268: +269: command <&1- +270: command 1<&1- +271: command >&1- +272: command 1>&1- +273: +274: # 3.6.10 Opening File Descriptors for Reading and Writing +275: +276: command <> test +277: command 1<>test +278: +279: # 4.1 Bourne Shell Builtins +280: +281: : a b c d +282: . file arg1 arg2 arg3 +283: break; break $VAR; break 1; break error here +284: cd; cd -L -e dir +285: continue; continue $VAR; continue 1; continue error here +286: eval a b c d +287: exec -c -a foo command a f g +288: exit; exit $VAR; exit 1; exit error here +289: export -fn -p VARNAME VAR="value" BASH CDPATH +290: getopts optstring NAME foo rrr ooo +291: hash -r -p name +292: pwd; pwd -L -P +293: readonly -aA VARNAME VAR="value" BASH IFS +294: return; return $VAR; return 1; return error here +295: shift; shift $VAR; shift 1; shift error here +296: test -x foo -o $ASD +297: [ -x foo -o $VAR ] +298: times; times error here +299: trap; trap -l -p a s df +300: umask -p -S 0444 +301: unset -f -n -v VAR1 VAR2 $VAR_IN_VAR CDPATH BASH +302: +303: # 4.2 Bash Builtin Commands +304: +305: alias; alias -p foo=bla +306: bind; bind -m aaa -f foo +307: builtin; builtin umask 0444 # <- should be as a command +308: caller; caller $VAR; caller 123 error here +309: command -pV grep here +310: declare -aA -p VAR1 VAR2=$FOO VAR3=$(command here) VAR4="str"'str'$'str' +311: echo -neE foo +312: enable -a -d fff +313: help -d patt +314: local -aA -p VAR1 VAR2=$FOO VAR3=$(command here) VAR4="str"'str'$'str' +315: logout; logout $VAR; logout 1; logout error here +316: mapfile -d 'f' file array +317: printf -v VAR 'format' foo +318: read -a -r VAR bla +319: readarray -d dd -C call array +320: source file; source file error here +321: type -af name +322: typeset -afFg VAR1 VAR2=$FOO VAR3=$(command here) VAR4="str"'str'$'str' +323: ulimit; ulimit -a; ulimit -H name +324: unalias; unalias -a; unalias name1 name2 +325: +326: let a=4 +327: let z=a++ +328: let y=--b +329: let result=~a +330: let "result=a<<2" +331: let "result=a&b" +332: let i=5 result=~a "result=a<<2" +333: let "myvar=7" "myvar2=4" "myvar3= myvar ^ myvar2" +334: +335: # 4.3.1 The Set Builtin +336: +337: set -a a b d +338: +339: # 4.3.2 The Shopt Builtin +340: +341: shopt -p -o opt +342: +343: # 5.2 Bash Variables +344: +345: $_ $BASH $BASHOPTS $BASHPID $BASH_ALIASES $BASH_ARGC +346: $BASH_ARGV $BASH_ARGV0 $BASH_CMDS $BASH_COMMAND $BASH_COMPAT $BASH_ENV +347: $BASH_EXECUTION_STRING $BASH_LINENO $BASH_LOADABLES_PATH $BASH_REMATCH +348: $BASH_SOURCE $BASH_SUBSHELL $BASH_VERSINFO $BASH_VERSION $BASH_XTRACEFD +349: $CHILD_MAX $COLUMNS $COMP_CWORD $COMP_LINE $COMP_POINT $COMP_TYPE $COMP_KEY +350: $COMP_WORDBREAKS $COMP_WORDS $COMPREPLY $COPROC $DIRSTACK $EMACS $ENV $EPOCHREALTIME +351: $EPOCHSECONDS $EUID $EXECIGNORE $FCEDIT $FIGNORE $FUNCNAME $FUNCNEST $GLOBIGNORE +352: $GROUPS $histchars $HISTCMD $HISTCONTROL $HISTFILE $HISTFILESIZE $HISTIGNORE +353: $HISTSIZE $HISTTIMEFORMAT $HOSTFILE $HOSTNAME $HOSTTYPE $IGNOREEOF $INPUTRC +354: $INSIDE_EMACS $LANG $LC_ALL $LC_COLLATE $LC_CTYPE $LC_MESSAGES $LC_NUMERIC +355: $LC_TIME $LINENO $LINES $MACHTYPE $MAILCHECK $MAPFILE $OLDPWD $OPTERR $OSTYPE +356: $PIPESTATUS $POSIXLY_CORRECT $PPID $PROMPT_COMMAND $PROMPT_DIRTRIM $PS0 $PS3 $PS4 +357: $PWD $RANDOM $READLINE_ARGUMENT $READLINE_LINE $READLINE_MARK $READLINE_POINT +358: $REPLY $SECONDS $SHELL $SHELLOPTS $SHLVL $SRANDOM $TIMEFORMAT $TMOUT $TMPDIR $UID +359: +360: ${#BASH} +361: +362: BASH=1 BASH=somestring +363: +364: # Bash variables in for loop +365: +366: for CDPATH; do +367: foo +368: done +369: +370: for CDPATH in 1 2 3; do +371: foo +372: done +373: +374: # Bash variables in commands that take variable names +375: +376: export CDPATH CDPATH=123 +377: unset CDPATH +378: +379: # 6.1 Invoking Bash +380: +381: bash; bash -c fff +382: +383: # 6.7 Arrays +384: +385: ADD=() +386: ARR=("val1" "val2" value\$one "val3" $(command here; echo \)) $'ansi-str') +387: ARR+=("val1" "val2" "val3" $(command here; echo \)) $'ansi-str') +388: ARR=(["foo"]="val1" [$VAR $VAR2 \] $VAR3]="val2" [$(V=1 command)]="foo" ["str"'str'$'\rstr']="str"'str'$'\rstr' ) +389: +390: ${!A[1]} ${!A["idx"]} +391: +392: ARR[1]="val" +393: +394: ARR["FOO"]="val" [sdfsdf] # '[sdfsdf]' is a command +395: ARR[$IDX]="val" +396: ADD[${IDX[0]}]="foo" # <- index as array element +397: ADD[${#IDX[@]}]="foo" # <- index as array element +398: +399: echo $A["foo"] # <- here is A["foo"] is not an array, it is "$A" and '["foo"]' +400: echo ${A["foo"]} # <- here is A["foo"] is an array +401: +402: A[$(echo bla)] # <- this should be the command 'A[bla]', not a variable/array +403: A[$(echo bla)]=1 command here foo # <- this should be an array assignment and a command +404: +405: A[fla echo 1]=1 # assignment +406: A[fla "echo]=" 1]=foo # assignment +407: echo ${A[fla "echo]=" 1]} # echo the assignment +408: +409: # Arrays + Shell Parameter Expansion +410: +411: ${A[foo]:-word} ${A['sdf']:=word} ${A[1]:?word} ${A[fff]:+word} +412: +413: ${A[foo]:0} ${A[$'bla']:0:10} ${A[$(command)]: -1} ${A[10]: -1:-10} +414: ${A[1]:$(( ${#B} + 10 )):$(command here)} ${A[foo]:"10":$'\r\t10'} +415: ${A[0]:7} ${A[0]:1:10} ${A[@]:1} ${A[*]:1} +416: +417: ${#A[foo]} +418: +419: ${A[1]#word} ${A[foo]##word} ${A['sdf']%word} ${A[$(test)]%%word} +420: +421: " ${A[1]#word} ${A[foo]##word} ${A['sdf']%word} ${A[$(test)]%%word} " # <- in double quoted strings +422: +423: ${A[10]/pat/str} ${A[foo]//pat/str} ${A["a"]/#pat/str} ${A[0]/%pat/str} +424: ${A[foo]/$(command)/`test`"dbl"$'ansi'} +425: +426: ${A[10]^pat} ${A[foo]^^pat} ${A["bla bla"],pat} ${A[iii],,pat} +427: ${A[0]^$(command here)} ${A[1],,`test`"sdfasdf"$'\r\t\e'} +428: +429: ${A[0]@U} ${A[1]@u} ${A[foo]@L} ${A["bla"]@Q} ${A[1]@E} +430: ${A[$'ansi']@P} ${A[$(command here)]@A} ${A[`command here`]@K} ${A[$VAR]@a} ${A[0]@k} +431: +432: # 6.8.1 Directory Stack Builtins +433: +434: dirs -c -l +N; dirs +435: popd; popd -n +436: pushd; pushd -n dir +437: +438: # 7.2 Job Control Builtins +439: +440: bg; bg 1 +441: fg; fg 1 error here +442: jobs; jobs -l 123 +443: kill; kill -l 1 +444: wait; wait -f 10 1 +445: disown; disown -a id $ID +446: suspend; suspend -f; suspend -f error here +447: +448: # 8.7 Programmable Completion Builtins +449: +450: compgen -o word +451: complete -a name name +452: compopt -o opt name +453: +454: # 9.2 Bash History Builtins +455: +456: fc; fc -e name +457: history; history 1; history -c +458: diff --git a/hrc/test/_valid/shell/shell-posix-spec.sh.html b/hrc/test/_valid/shell/shell-posix-spec.sh.html new file mode 100644 index 00000000..acd28115 --- /dev/null +++ b/hrc/test/_valid/shell/shell-posix-spec.sh.html @@ -0,0 +1,921 @@ + 0: #!/bin/sh + 1: + 2: # ------------------------------------------------------------------------ + 3: # POSIX doc: + 4: + 5: # 2.2 Quoting + 6: \| \& \; \> \< \( \) \$ \` \\ \" \' no meaning + 7: test for no meaning for new line \ + 8: I_AM_NOT_VARIABLE=1 command \ + 9: if doesn\'t work also + 10: + 11: # 2.2.2 Single-Quotes + 12: 'single quote string' 'escape does not \work here' + 13: + 14: # 2.2.3 Double-Quotes + 15: double quoted "only these chars should be escaped \$, \`, \", \\, but \nothing \! else" + 16: + 17: # 2.4 Reserved Words + 18: ! command + 19: # Everything is marked as errors, except 'in' + 20: do elif else + 21: elif + 22: elif VAR=1 some command here >&1 + 23: else + 24: in + 25: then + 26: # the following words are in their blocks: + 27: # case/esac if/fi for/done while/done until/done + 28: # + 29: # Special cases + 30: # + 31: # Only the first reserved word must be highlighted + 32: do elif else + 33: # + 34: + 35: # 2.5.2 Special Parameters + 36: $@ $* $# $? $- $$ $0 + 37: ${@} ${*} ${#} ${?} ${-} ${$} ${0} + 38: + 39: # 2.5.3 Shell Variables + 40: $ENV $HOME $IFS $LANG $LC_ALL $LC_COLLATE $LC_TYPE $LC_MESSAGES + 41: $LINENO $NLSPATH $PATH $PPID $PS1 $PS2 $PS4 $PWD + 42: + 43: $PATH_SEPARATOR # <- this is not a shell variable + 44: + 45: ${ENV} ${HOME} ${IFS} ${LANG} ${LC_ALL} ${LC_COLLATE} ${LC_TYPE} ${LC_MESSAGES} + 46: ${LINENO} ${NLSPATH} ${PATH} ${PPID} ${PS1} ${PS2} ${PS4} ${PWD} + 47: + 48: ENV=1 HOME=2 IFS=3 LANG=foo LC_ALL=bar LC_COLLATE=xxx LC_TYPE=1 LC_MESSAGES=2 + 49: LINENO=1 NLSPATH=bla PATH=11 PPID=r PS1=x PS2=+ PS4=e PWD=5 + 50: + 51: # 2.6.2 Parameter Expansion + 52: ${ASD-fo br} ${ASD:-fo" br"} ${ASD='br bz'} ${ASD:=br \{ bo} + 53: ${ASD?$VARH} ${ASD:?"$QVAR"} ${ASD+$(V=1 cmd re)} ${ASD:+`V=1 a here`} + 54: ${1-foo bar} ${1:-foo" bar"} ${1='bar baz'} ${1:=bar \{ boo} + 55: ${1?$VARHERE} ${1:?"$QVAR"} ${1+$(V=1 cmd here)} ${1:+`V=1 a here`} + 56: + 57: ${#ASD} ${#1} + 58: + 59: ${ASD%fo ba} ${ASD%%fo" br"} ${ASD#'bz bz'} ${ASD##br \{ bo} + 60: ${1%$VARH} ${1%%"$QVAR"} ${1#$(V=1 cmd re)} ${1##`V=1 a here`} + 61: + 62: $ASD $1 + 63: + 64: # Word break characters should not be considered as the end of + 65: # the parameter extension. + 66: + 67: ${A%foo # bar} + 68: ${A%foo ; command} + 69: ${A%foo > command} + 70: ${A%foo ) command} + 71: ${A%foo ( command} + 72: ${A%foo & command} + 73: ${A%foo | command} + 74: + 75: A=123 A="sdfasdf" A=$(V=1 command here 2>/dev/null) B=`cd asd` + 76: A=123; cd test + 77: A=1|B=2|topipe command + 78: A=1;nextcmd + 79: A=1>A=1 cmd here # <- 'A=1' is not a variable assignment, it is a file + 80: + 81: # 2.6.3 Command Substitution + 82: exec 1 $( { V=123 V2="sdsdf"; }; execute something 2>&1 1>/dev/null && X=1 echo 123 V=1) + 83: exec 2 "$(V=123 V2="sdsdf" execute something 2>&1 1>/dev/null && X=1 echo 123 V=1)" + 84: exec 3 `V=123 V2="sdsdf" execute something 2>&1 1>/dev/null && X=1 echo 123 V=1` + 85: exec 4 "`V=123 V2="sdsdf" execute something 2>&1 1>/dev/null && X=1 echo 123 V=1`" + 86: + 87: # nested (not implemented, TODO?) + 88: exec 3 `V=123 V2="sdsdf" \`X=1 echo 123 V=1\` more params` + 89: exec 4 "`V=123 V2="sdsdf" \`X=1 echo 123 V=1\` more params`" + 90: + 91: # 2.6.4 Arithmetic Expansion + 92: $(( X + B << 2 * 10 / 30 + $X - $1 % "123" )) + 93: A=$(( X + B << 2 * 10 / 30 )) + 94: A="$(( X + B << 2 * 10 / 30 ))" + 95: + 96: # 2.7.1 Redirecting Input + 97: foo < bla + 98: foo 0< bla + 99: +100: # 2.7.2 Redirecting Output +101: foo > bla +102: foo 2>bla +103: foo 2>|bla +104: +105: # 2.7.3 Appending Redirected Output +106: foo >> bla +107: foo 2>>bla +108: +109: # 2.7.4 Here-Document +110: Non quoted here-doc 2<<BLA +111: If no part of word is ${quoted}, all lines of the here-document shall be +112: expanded for $parameter ${expansion}, `A=1 command` $(B=2 substitution >/dev/null), +113: and $((arithmetic expansion + 1 / 10)). In this case, the <backslash> in the input +114: behaves as the <backslash> inside double-quotes (see Double-Quotes). +115: ( Here we are \$, \`, \", \\, but \nothing \! else ) +116: However, the double-quote character ( ' )' shall not be treated specially +117: within a here-document, except when the double-quote appears +118: within "$()", "``", or "${}". (WTF?!) +119: BLA +120: +121: Quoted here-doc <<-"FOO" +122: If any part of word is quoted, the delimiter shall be formed by performing +123: quote removal on word, and the here-document lines $shall not be $(expanded). +124: FOO +125: +126: Single-quoted here-doc <<'FOO' +127: not $expanded +128: FOO +129: +130: heredoc after redirection >foobar << BLA +131: with space before label +132: BLA +133: +134: # 2.7.5 Duplicating an Input File Descriptor +135: 1<&2 <&- +136: +137: # 2.7.6 Duplicating an Output File Descriptor +138: 1>&2 2>&- +139: +140: # 2.7.7 Open File Descriptors for Reading and Writing +141: <>/blabla 1<> /blabla +142: +143: # 2.9.1 Simple Commands / Command Search and Execution / builtin +144: # The command must be on the first place +145: alias foo=bla +146: bg alias cd +147: cd command A1=11 +148: DEFINE_VAR=1 command +149: false +150: DEFINEVAR=2 command cd alias >/dev/null +151: DEFVAR=1 fc 1>&1 +152: fg +153: getopts more parameters here +154: hash THIS_IS_PARAMETER_BUT_NOT_VARIABLE=1 +155: jobs +156: kill +157: newgrp +158: pwd +159: read +160: true +161: umask +162: unalias +163: wait while do for in +164: # +165: # Special cases: +166: # +167: # Only the first buildin command must be highlighted +168: alias bg cd hash +169: # variables after buildin command must not be highlighted as are plain parameters +170: # however, variables after reserved words must be highlighted +171: alias VAR1=1 +172: # reserved words must not be highlighted after builtin command +173: command while something; command +174: +175: # 2.9.2 Pipelines +176: VAR1=1 foo bla | VAR=2 ! test cmd # exclamation mark is NOT highlighted +177: +178: # 2.9.3 Lists +179: VAR1=1 foo bla && ! VAR=2 test cmd || VAR=3 command read # exclamation mark is highlighted +180: VAR=1 foo & && VAR=2 test cmd +181: R=1 date && V=1 who || VAR=1 ls; VAR=2 cat file +182: V=1 wc file > output & R=1 true +183: # Asynchronous Lists +184: V=1 background1 & V=2 background2 +185: # Sequential Lists +186: V=1 command1; V=2 command2 +187: +188: # 2.9.4 Compound Commands +189: ( V1=1 grouped command1; V=1 command2 ) +190: ( +191: V1=1 command1 here +192: V2=2 command2 +193: ( +194: V2= nested +195: { +196: V3=1 nested +197: } +198: ) +199: ) +200: ( V1=1 command1 +201: V2=2 command2 \) ) +202: +203: { V1=1 group 1; V1= command2 here should be an error here because of the missing semicolon } +204: } # this one works +205: { cmd1; cmd2; no error here; } +206: { +207: cmd1 +208: V1=cmd1 +209: { +210: nested +211: \} +212: } +213: } +214: +215: if +216: fi # <- error here, there is no 'then' +217: then +218: fi # <- close the above 'if' +219: +220: # The for Loop +221: +222: for IFS in 1 2 3 # comment here +223: do +224: done +225: +226: for IFS in $(V1=val command) 2 3; do command; done; # check special variable +227: for "IFS" in $(V1=val command) 2 3; do command; done; # check variable in quotes +228: +229: for var in $VAR; do +230: +231: done +232: +233: for var in; error here do done +234: do +235: done +236: +237: for var in; error here; do done +238: +239: for var in; do done +240: +241: for VAR in "BLA" "FOO" "BAR"; do; done +242: +243: for VAR # comment here +244: do +245: done +246: +247: for $(V1=val command here); do +248: command +249: done +250: +251: for VAR error here; do +252: done +253: +254: for VAR; do +255: command +256: if [ -n "$FOO" ]; then +257: something +258: fi +259: done +260: +261: for IFS; do command; done; # check special variable +262: +263: for "IFS"; do command; done; # variable in quotes <- 'in' word must not activate the 'in' syntax for form +264: for "IFS"; do command; done; # variable _in quotes +265: +266: # Case Conditional Construct +267: +268: case $FOO in +269: a aaaaa pat1) A=1 xdo; A=2 something ;; +270: pat2|fff\) BLA=123) B=2;; +271: pat3) +272: A=x cmd;; +273: pat4) +274: B=1 cmd +275: C=3 cmd1 +276: if [ -x "$BLA" ]; then +277: ffff +278: case $BLA in +279: fff) F=1;; +280: bla) no the last ";;" here +281: esac +282: fi +283: ;; +284: here pat) T=1 ttt;; +285: $VAR_HERE) cmd;; +286: $(V1=1 some command here)) cmd2;; +287: *) bla +288: fooo +289: ;; +290: esac +291: +292: # The if Conditional Construct +293: +294: if foo; then +295: C=1 cmd here 2>/dev/null +296: fi +297: +298: if [ $BLABLA -gt 1 ]; then VAR=HERE cd blalbla; fi +299: +300: if [ -x "$N" ]; then +301: alias skdfjlkj +302: elif V=1 some command here; then +303: V1=1 anything here +304: blalba +305: elif [ -t -o 1 -x ]; then +306: X=1 ffff +307: else +308: command here +309: fi +310: +311: if [ $BLABLA != "123" ]; then +312: X=1 somecmd sfasfasd sfsfasdf afa sdf sdf; +313: if foo; then +314: cd sdfkjkjfkj +315: fi +316: fi +317: +318: if V=1 command here +319: then +320: V1=2 we do something +321: if nested; then +322: nothing to do +323: fi +324: fi +325: +326: # The while Loop +327: +328: while true; do +329: something +330: done +331: +332: while [ -x "$BLA" ]; do something here; done +333: while [ -x "FOO" ]; do while bla; do nothing; done; done +334: +335: while x 2>&1; do +336: while nested; do +337: nothing +338: done +339: done +340: +341: # The until Loop +342: +343: until true; do +344: something +345: done +346: +347: until [ -x "$BLA" ]; do something here; done +348: +349: until x 2>&1; do +350: while nested; do +351: until [ -x nested ]; do +352: nothing +353: done +354: done +355: done +356: +357: # 2.9.5 Function Definition Command +358: +359: somefn() sfkjskdfj; +360: no fn here +361: +362: somefn () { +363: still fn +364: bla +365: fnd2() { +366: another fn +367: } +368: } +369: +370: somefn() +371: +372: errorfn() { blalbla } +373: close the curved bracket from above; } +374: +375: func( ) cmd function with space between brackets +376: func ( ) cmd function with space between brackets#2 +377: +378: # 2.14. Special Built-In Utilities +379: +380: # NAME +381: # break - exit from for, while, or until loop +382: # SYNOPSIS +383: # break [n] +384: +385: break +386: break; break; break +387: break 10 +388: break "$VAR"; break '123' +389: break a10 # <- errors here +390: break; break 10; break error here; break 1; # the last is ok +391: break error here +392: break; # this is ok +393: break $SOMEVAR but error here +394: break $(V=1 eval something here) but error here +395: +396: # NAME +397: # colon - null utility +398: # SYNOPSIS +399: # : [argument...] +400: +401: : +402: : highlight only $VAR here and $(V=1 evaluations) +403: +404: # NAME +405: # continue - continue for, while, or until loop +406: # SYNOPSIS +407: # continue [n] +408: +409: continue +410: continue; continue; continue 10 20 # second parameter is an error +411: continue 10 +412: continue a10 # <- errors here +413: continue; continue 10; continue error here; continue 1; # the last is ok +414: continue error here +415: continue; # this is ok +416: continue $SOMEVAR but error here +417: continue $(V=1 eval something here) but error here +418: +419: # NAME +420: # dot - execute commands in the current environment +421: # SYNOPSIS +422: # . file +423: +424: . file; . tttt +425: . file 2>/dev/null error here; +426: . file; . file $VAR error here; command next here +427: . file; . file error here # comment here +428: +429: # NAME +430: # eval - construct command by concatenating arguments +431: # SYNOPSIS +432: # eval [argument...] +433: +434: eval "something" 2>/dev/null +435: eval "something" +436: eval "one" "two" $(V1=1 cmd3 >/dev/null) +437: eval; V=1 another command here +438: eval ; V=1 another command here +439: eval # comment here +440: +441: # NAME +442: # exec - execute commands and open, close, or copy file descriptors +443: # SYNOPSIS +444: # exec [command [argument...]] +445: +446: exec command is not highlighted as buildin 1>/dev/null +447: exec; V1=1 command here +448: exec ; V1=1 command here too +449: exec 3< readfile +450: exec 4> writefile +451: exec 5<&0 +452: exec 3<&- +453: foo=bar exec cmd +454: +455: # NAME +456: # exit - cause the shell to exit +457: # SYNOPSIS +458: # exit [n] +459: +460: exit +461: exit; exit; exit +462: exit 10 +463: exit a10 # <- errors here +464: exit; exit 10; exit error here; exit 1; # the last is ok +465: exit error here +466: exit; # this is ok +467: exit $SOMEVAR but error here +468: exit $(V=1 eval something here) but error here +469: +470: # NAME +471: # export - set the export attribute for variables +472: # SYNOPSIS +473: # export name[=word]... +474: # export -p +475: +476: export ; export VAR FOO BLA=1 PATH $IFS PATH=123 -wrong variable name +477: export X="fff" R="$(V=1 cmd here)" $VAR_ALSO 'quoted' 1wrong variable name +478: export -p; export only; #comment here +479: export -p a # <- error here +480: export -p error here; export VAR one two +481: export X=$(false) +482: +483: # NAME +484: # readonly - set the readonly attribute for variables +485: # SYNOPSIS +486: # readonly name[=word]... +487: # readonly -p +488: +489: readonly +490: readonly 1>/a123 FFF # <- error here +491: readonly DFF 1>/b123 +492: readonly; readonly VAR FOO BLA=1 PATH $IFS PATH=123 -wrong variable name +493: readonly X="fff" R="$(V=1 cmd here)" $VAR_ALSO 'quoted' 1wrong variable name +494: readonly -p; readonly only; #comment here +495: readonly -p a # comment here +496: readonly -p error here; readonly VAR one two +497: readonly X=$(false) +498: +499: # NAME +500: # return - return from a function or dot script +501: # SYNOPSIS +502: # return [n] +503: +504: return +505: return 2>/dev/null error here +506: return 10 2>/dev/null error here +507: return; return; return +508: return 10 +509: return a10 <- errors here +510: return; return 10; return error here; return 1; # the last is ok +511: return error here +512: return; # this is ok +513: return $SOMEVAR but error here +514: return $(V=1 eval something here) but error here +515: +516: # NAME +517: # set - set or unset options and positional parameters +518: # SYNOPSIS +519: # set [-abCefhmnuvx] [-o option] [argument...] +520: # set [+abCefhmnuvx] [+o option] [argument...] +521: # set -- [argument...] +522: # set -o +523: # set +o +524: +525: set +526: set; set +a 1>/dev/null +527: set -o option $(cmd here); set -- "$VAR" +528: set -o +529: set +o +530: +531: # NAME +532: # shift - shift positional parameters +533: # SYNOPSIS +534: # shift [n] +535: +536: shift +537: shift 2>/dev/null error here +538: shift; shift; shift +539: shift 10 +540: shift a10 <- errors here +541: shift; shift 10; shift error here; shift 1; # the last is ok +542: shift error here +543: shift; # this is ok +544: shift $SOMEVAR but error here +545: shift $(V=1 eval something here) but error here +546: +547: # NAME +548: # times - write process times +549: # SYNOPSIS +550: # times +551: +552: times; times error here; #comment here +553: times aaa # comment here +554: times error here; times 2>/dev/null sdfsdfasf +555: +556: # NAME +557: # trap - trap signals +558: # SYNOPSIS +559: # trap n [condition...] +560: # trap [action condition...] +561: +562: trap 1 SIG1 SIG2 $SIG_AS_VARIABLE $(command here) +563: trap "some sction" SIG1 SIG2 2>/dev/null; V=1 the next command here +564: trap 1 1>/dev/null +565: +566: # NAME +567: # unset - unset values and attributes of variables and functions +568: # SYNOPSIS +569: # unset [-fv] name... +570: +571: unset -x; #<- error here +572: unset; +573: unset -f; unset -v; unset -fv; unset -vf +574: unset -f VAR VAR2; unset -v VAR VAR2; unset -vf VAR VAR ERR_HERE=1 +575: unset VAR VAR2 IFS VAR3 $(V=1 cmd here) "quote" 'single' 2>/dev/null +576: unset VAR=234 FFFgger; # <- error here, no assignments +577: +578: # 4. Utilities +579: +580: # Special cases +581: +582: test -x /some/file -o -n "$BLABLA" && test -n "$VAR" +583: +584: batch; batch error hereas; batch $(AGAIN ERROR) fasdf # comment here +585: +586: false; false error here; #comment +587: +588: true; true error here; #comment +589: +590: logname; logname error here; #comment +591: +592: sleep; sleep 10; sleep $VAR; sleep a10 # <- error here +593: +594: tty; tty error here; #comment +595: +596: dirname; dirname $A; dirname test error here ;# comment +597: dirname $VAR error here; dirname foo +598: +599: uname; uname -a; #comment here +600: uname -a error here +601: +602: # Common cases +603: +604: alias; +605: alias name; alias name='string' # comment here +606: alias name=$FOO; # comment here +607: ar -x; ar -r; #comment here +608: ar +609: ar; ar -p +610: at -l -1 bla; at; at -m '10' $(V1=1 cmd run) +611: awk; awk -F bla; awk $(TE=1 cmd) # comment here +612: basename; basename bla; basename $(TE=1 cmd) # comment here +613: bc; bc -l; bc foo $(V1=1 cmd) $VAR_HERE; # comment +614: bg; bg $ID; #comment here +615: cal 1 2020; cal; cal 1 $(C1=1 cmd here); #comment +616: cat; cat -u; cat /some/file; cat $FROM_VAR; # comment +617: cd -; cd /foo/bar; cd -L; # comment +618: chgrp; chgrp -h ${GROUP} /some/file; # comment +619: chmod; chmod -R 0666 /some/file; chmod -R; # comment +620: chown; chown -h root:root /some/file; chown -R; # comment +621: cksum; cksum /file; cksum ${VAR}; # comment +622: cmp; cmp -l; cmp file1 file2; # comment +623: comm; comm -1 file1 file2; comm $(V=1 cmd here); # comment +624: command some command here; command cd $FOO; #comment +625: compress; compress -c file; #comment +626: cp; cp a b; #comment +627: crontab; crontab file; #comment +628: csplit; csplit -k file; #comment +629: cut; cut -d1 -f; #comment +630: date; date +Z; # comment +631: dd; dd if=bla; #comment +632: df; df -m; # comment +633: diff; diff -r ba br; #comment +634: du; du foo; # comment +635: echo; echo "$SOMETHING"; #comment here +636: ed; ed bbbb; # comment +637: env; env foo; #comment +638: ex; ex file; #comment +639: expand; expand foo; #comment +640: expr; expr $A + 1; #comment +641: fc; fc -l; #comment here +642: fg; fg $ID; #comment here +643: file; file /dev/$FILE; #comment +644: find; find -x $XXX; #comment +645: fold; fold -bs /some/file; #comment +646: fuser; fuser -c /some/file; #comment +647: getconf; getconf $VAR; #comment +648: getopts; getopts "$VAR"; #comment +649: grep; grep blalba $VAR; #comment +650: hash; hash $FOO; #comment +651: head; head -n 1; head /file/$VAR; #comment +652: iconv; iconv -f bla -t foo; #comment +653: id; id -a; id $USER; #comment +654: ipcrm; ipcrm -q $ID; #comment +655: ipcs; ipcs -q $VAR; #comment +656: jobs; jobs -l; #comment +657: join; join -a $VAR; #comment +658: kill; kill -9 #ID; #comment +659: link; link file $VAR; #comment +660: ln; ln -s /ffff $VAR; #comment +661: locale; locale -a $VAR; #comment +662: localedef; localedef -a; #comment +663: logger; logger -a; #comment +664: ls; ls -a /foo; #comment here +665: mailx; mailx $FOO; #comment here +666: make; make -f makefile; # comment here +667: man; man foo; #comment here +668: mesg; mesg --option; #comment here +669: mkdir; mkdir -p; #comment here +670: mkfifo; mkfifo $FOO; #comment here +671: more; more $FOO; #comment here +672: mv; mv -f foo bla; #comment here +673: newgrp; newgrp -n $VAR; #comment here +674: nice; nice -c 1; #comment here +675: nl; nl $FOO; # comment here +676: nm; nm $FOO; #comment here +677: nohup; nohup test; #comment here +678: od; od $FOO; # comment here +679: paste; paste /from/file; #comment here +680: patch; patch -p0 /patch/file; #comment here +681: pathchk; pathchk $FOO; #comment here +682: pr; pr $FOO; #comment here +683: printf; printf -v BLA 'STRING'; #comment here +684: ps; ps -a; #comment here +685: pwd; pwd -L; #comment here +686: read; read -r VAR; #comment here +687: renice; renice -a; #comment here +688: rm; rm -rf; #comment here +689: rmdir; rmdir /test; #comment here +690: sed; sed -i $VAR; #comment here +691: sh; sh -c $FOO; #comment here +692: sort; sort $FOO; #comment here +693: split; split $FOO; #comment here +694: strings; strings /some/file; #comment here +695: strip; strip $FOO; #comment here +696: stty; stty -a; #comment here +697: tabs; tabs -t; #comment here +698: tail; tail -f /foo; #comment here +699: tee; tee /foo/bar; #comment here +700: time; time -a $VAR; #comment here +701: touch; touch $FOO; #comment here +702: tput; tput $FOO; #comment here +703: tr; tr 'ff' 'bbb'; #comment here +704: tsort; tsort $FILE; #comment here +705: type; type -p; #comment here +706: ulimit; ulimit -t; #comment here +707: umask; umask 0444; #comment here +708: unalias; unalias -a; #comment here +709: uncompress; uncompress $FOO; #comment here +710: unexpand; unexpand $FOO; #comment here +711: uniq; uniq --help; #comment here +712: unlink; unlink $FILE; #comment here +713: vi; vi $FILE; #comment here +714: wait; wait $PID1 $PID2; #comment here +715: wc; wc -l; wc $FILE; #comment here +716: who; who -a; who am i; #comment here +717: write; write $TEST; #comment here +718: xargs; xargs $FOO $BLA; #comment here +719: zcat; zcat $FILE; #comment here +720: +721: # The usual chunks of code from: +722: # https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html +723: +724: a=1 +725: set 2 +726: echo ${a}b-$ab-${1}0-${10}-$10 +727: +728: foo=asdf +729: echo ${foo-bar}xyz} +730: +731: ${x:-$(ls)} +732: +733: unset X +734: echo ${X:=abc} +735: +736: unset posix +737: echo ${posix:?} +738: +739: set a b c +740: echo ${3:+posix} +741: +742: HOME=/usr/posix +743: echo ${#HOME} +744: +745: x=file.c +746: echo ${x%.c}.o +747: +748: x=posix/src/std +749: echo ${x%%/*} +750: +751: x=$HOME/src/cmd +752: echo ${x#$HOME} +753: +754: x=/one/two/three +755: echo ${x##*/} +756: +757: "${x#*}" +758: +759: ${x#"*"} +760: +761: # repeat a command 100 times +762: x=100 +763: while [ $x -gt 0 ] +764: do +765: command +766: x=$(($x-1)) +767: done +768: +769: # nested heredocs are not supported +770: #cat <<eof1; cat <<eof2 +771: cat <<eof1 > /some/file +772: Hi, +773: eof1 +774: Helene. +775: eof2 +776: +777: false && echo foo || echo bar +778: true || echo foo && echo bar +779: +780: while +781: # a couple of <newline>s +782: +783: +784: # a list +785: date && who || ls; cat file +786: # a couple of <newline>s +787: +788: +789: # another list +790: wc file > output & true +791: +792: +793: do +794: # 2 lists +795: ls +796: cat file +797: done +798: +799: for i in * +800: do +801: if test -d "$i" +802: then break +803: fi +804: done +805: +806: foo() { +807: for j in 1 2; do +808: echo 'break 2' >/tmp/do_break +809: echo " sourcing /tmp/do_break ($j)..." +810: # the behavior of the break from running the following command +811: # results in unspecified behavior: +812: . /tmp/do_break +813: +814: +815: do_continue() { continue 2; } +816: echo " running do_continue ($j)..." +817: # the behavior of the continue in the following function call +818: # results in unspecified behavior (if execution reaches this +819: # point): +820: do_continue +821: +822: +823: trap 'continue 2' USR1 +824: echo " sending SIGUSR1 to self ($j)..." +825: # the behavior of the continue in the trap invoked from the +826: # following signal results in unspecified behavior (if +827: # execution reaches this point): +828: kill -s USR1 $$ +829: sleep 1 +830: done +831: } +832: for i in 1 2; do +833: echo "running foo ($i)..." +834: foo +835: done +836: +837: : ${X=abc} +838: if false +839: then : +840: else echo $X +841: fi +842: +843: x=y : > z +844: +845: for i in * +846: do +847: if test -d "$i" +848: then continue +849: fi +850: printf '"%s" is not a directory.\n' "$i" +851: done +852: +853: cat foobar +854: . ./foobar +855: echo $foo $ba +856: +857: eval " $commands" +858: eval " $(some_command)" +859: foo=10 x=foo +860: y='$'$x +861: echo $y +862: eval y='$'$x +863: echo $y +864: +865: exec 3< readfile +866: exec 4> writefile +867: exec 5<&0 +868: exec 3<&- +869: exec cat maggie +870: foo=bar exec cmd +871: +872: exit 0 +873: exit 1 +874: ( +875: command1 || exit 1 +876: command2 || exit 1 +877: exec command3 +878: ) > outputfile || exit 1 +879: echo "outputfile created successfully" +880: +881: export X=$(false) +882: X=$(false) +883: export X +884: +885: export PWD HOME +886: export PATH=/local/bin:$PATH +887: export -p > temp-file +888: unset a lot of variables +889: +890: set -e +891: start() { +892: some_server +893: echo some_server started successfully +894: } +895: start || echo >&2 some_server failed +896: set +897: set c a b +898: set -xv +899: set -- +900: set -- "$x" +901: set -- $x +902: set -- "$@" +903: +904: trap "jobs -n" CLD +905: +906: set a b c d e +907: shift 2 +908: echo $* +909: +910: save_traps=$(trap) +911: eval "$save_traps" +912: +913: trap '"$HOME"/logout' EXIT +914: trap '"$HOME"/logout' 0 +915: trap - INT QUIT TERM EXIT +916: +917: trap 'read foo; echo "-$foo-"' 0 +918: trap 'eval " $cmd"' 0 +919: trap " $cmd" 0 +920: diff --git a/hrc/test/_valid/shell/test.sh.html b/hrc/test/_valid/shell/test.sh.html new file mode 100644 index 00000000..2fd1f58e --- /dev/null +++ b/hrc/test/_valid/shell/test.sh.html @@ -0,0 +1,9 @@ +0: +1: #!/bin/sh +2: (cd x; y/a-b.sh) +3: +4: echo ${#aoeu[@]} +5: +6: DATE=`date` +7: echo $DATE +8: diff --git a/hrc/test/shell/shell-bash-spec.bash b/hrc/test/shell/shell-bash-spec.bash new file mode 100644 index 00000000..98e4cd01 --- /dev/null +++ b/hrc/test/shell/shell-bash-spec.bash @@ -0,0 +1,458 @@ +#!/usr/bin/env bash + +# 3.1.2.4 ANSI-C Quoting + +$'\nfoo\e' +A=$'\\\'\"\?no special meaning' +CDPATH=$'octal \1 \12 \123 foo' $'octal error \9 \19 \181 foo' +command ${CDPATH%$'test\rtest'} `in backquote $'test\1test'` +( in subshell $'\1' ) +{ in group $'1'; } +command $'hex \x1 \x1a \xFFnospecial meaning' +A=$(foo $'unicode \u1 \uF1 \uFFA \udeadno special meaning') +$'unicode \U1 \UF1 \UFFA \Udead \UDEAD1 \U12345 \U123456 \U1234567 \U12345678no special meaning' +$'control-x \cx no cpecial meaning' + +# 3.1.2.5 Locale-Specific Translation + +$"some message" +A=$"some message $VAR inside" +CDPATH=$"msg $'ansi-c\\here\r'" +command ${CDPATH%$"msg $(command)"} +( in subshell $"msg" ) +{ in group $"msg"; } +A=$(foo $"something $'ansi-c\t\\' ${CDPATH#$"msg"}") `in bq $"some\$th\\i\ng"` + +# 3.2.5.1 Looping Constructs +# for (( expr1 ; expr2 ; expr3 )) ; do commands ; done + +for (( i = 0; $i < $VAR; i++ )); do + cmd +done + +for (( i = 0; i < $VAR; i++ )); do + cmd +done + +for (( i = 0; $i < '$NO_VAR'; i = $i + $'ansi-c' )) +do + cmd +done + +for (( i = "123"; $i < ${CDPATH}; i = $i / 100 )); do V1=456 command here; done +for ((;;)); do V1=456 command here; done + +# 3.2.5.2 Conditional Constructs + +# select + +select var in $VAR; do + +done + +select var in; do done + +select VAR in "BLA" "FOO" "BAR"; do; done + +select VAR; do + command + if [ -n "$FOO" ]; then + something + select VAR; do + done + fi + select VAR; do + select VAR; do + done + done +done + +select IFS in; do done # POSIX special variable +select CDPATH in; do done # Bash special variable + +( select VAR; do done ) +{ select VAR; do done; } + + +# (( ... )) + +(( "asd" '123' $'\r\t123' $"foo" 1 )) # test strings / numbers +(( $(V1=1 command) `command` )) # evaluations +(( \$ \" \' \$ )) # escapes +(( $VAR $IFS $CDPATH )) # variables +(( ${VAR%10} ${IFS#10} ${CDPATH%10} )) # parameter expansion +(( i++ i-- ++IFS --CDPATH )) # increment / decrement +(( 1 + 1 - 2 ! 1 ~ 3 ** 3 * 4 / 5 % -6 >> 10 << 20 )) # operations +(( 1 <= 2 >= 4 < 1 > 4 == 5 != 4 & 1 ^ 5 | 8 && 10 || 20 ? 30 : 2 )) # operations +(( a = 1 || w *= 1 || IFS /= 10 || CDPATH %= 10 || x += 10 || y -= 10 )) # assignment +(( a <<= 10 || b >>= 30 || c &= 1 || f |= 40 )) # assignment + +(( 0174 + 0$VAR + 8#123 + 09874 + 8#845 )) # octal + octal var + bad octal numbers +(( 0x12F + 0XDeaDBeEf111 + 0x$VAR + 16#411Ab + 0x1Z23 + 16#123K )) # hex + hex var + bad hex numbers +(( 3#10 + 10#$VAR + 44#50 + 65#567 )) # any base + wrong base (65+) +(( 2#45 + 10#45A )) # bad bin/dec bases + +# [[ ... ]] + +[[ a -f e || -f /bla || -o fofofof || -v varname || -R varname && -z "$STRING" ]] +[[ 1 > 2 ]] +[[ "asd" '123' $'\r\t123' $"foo" 1 ]] # test strings / numbers +[[ $(V1=1 command) `command` ]] # evaluations +[[ \$ \" \' \$ ]] # escapes +[[ $VAR $IFS $CDPATH ]] # variables +[[ ${VAR%10} ${IFS#10} ${CDPATH%10} ]] # parameter expansion +[[ $fffj =~ [[:space:]]*(a)?b ]] +[[ $line =~ ^"initial string" ]] +[[ $line =~ "^initial string" ]] +pattern='[[:space:]]*(a)?b' +[[ $line =~ $pattern ]] +[[ $line =~ $CDPATH ]] # special variable +[[ 'Hello World' =~ Hello ]] +[[ $digit =~ [0-9] ]] +[[ $REPLY =~ ^[0-9]+$ ]] # special variable +[[ "$email" =~ ^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+.[A-Za-z]{2,4}$ ]] +[[ $ip =~ ^[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}$ ]] + +# 3.2.6 Coprocesses + +coproc CDPATH { + select far in; do + done +} 2>/dev/null + +coproc name_as_variable { V=1 command here; } 2>/dev/null 1/dev/null + +coproc name_as_var { + V=1 command here +} + +coproc { + V1=1 command here +} + +# 3.3 Shell Functions + +func-name () command here 2>/dev/null + +func%name () { + command here +} 2>/dev/null + +func-name () { command here; } + +,func-name-comma () { command here; } + +function fu1[nc]name command here 1>/dev/null + +function f-un[c () command here + +function f123 () { + command here +} + +function func-name { command here; } + +function -error here; + +# 3.5.3 Shell Parameter Expansion + +${A:-word} ${BASH:-word} +${A:=word} ${BASH:=word} +${A:?word} ${BASH:?word} +${A:+word} ${BASH:+word} + +${A:0} ${A:0:10} ${A: -1} ${A: -1:-10} ${BASH:0} ${BASH:0:10} ${BASH: -1} ${BASH: -1:-10} +${@:7} ${@:1:2} ${*:1} ${*:1:2} +${A:$(( ${#B} + 10 )):$(command here)} ${A:"10":$'\r\t10'} + +${!prefix*} ${!prefix@} ${!1@} + +${!name[@]} ${!name[*]} +${!A} ${!BASH} ${!1} ${!@} + +${#A} ${#BASH} ${#*} ${#@} +${A#word} ${BASH#word} ${A##word} ${BASH##word} +${A%word} ${BASH%word} ${A%%word} ${BASH%%word} + +${A/pat/str} ${BASH/pat/str} ${A//pat/str} ${BASH//pat/str} +${A/#pat/str} ${BASH/#pat/str} ${A/%pat/str} ${BASH/%pat/str} +${A/$(command)/`test`"dbl"$'ansi'} + +" ${A/pat/str} ${A/$(command)/`test`"dbl"$'ansi'} " # <- in double quoted strings + +${A^pat} ${BASH^pat} ${A^^pat} ${BASH^^pat} +${A,pat} ${BASH,pat} ${A,,pat} ${BASH,,pat} +${A^$(command here)} ${BASH,,`test`"sdfasdf"$'\r\t\e'} + +${A@U} ${A@u} ${A@L} ${A@Q} ${A@E} ${A@P} ${A@A} ${A@K} ${A@a} ${A@k} +${BASH@U} ${BASH@u} ${BASH@L} ${BASH@Q} ${BASH@E} ${BASH@P} ${BASH@A} ${BASH@K} ${BASH@a} ${BASH@k} + +for i in; do + "'${M:$i:1}" # <- test in for loop +done + +# 5.1 Bourne Shell Variables + +$CDPATH $HOME $IFS $MAIL $MAILPATH $OPTARG $OPTIND $PATH $PS1 $PS2 + +${#CDPATH} + +CDPATH=1 CDPATH=somestring + +# 3.5.6 Process Substitution + +command here <(V=1 command here) >(V=1 command here) + +command here < <(V=1 command here) + +# 3.6 Redirections + +ls > dirlist 2>&1 +ls 2>&1 > dirlist + +# 3.6.1 Redirecting Input + +command < test < $VAR +command 2< test 1<$CDPATH + +# 3.6.2 Redirecting Output + +command >test >$VAR +command >|test >|$VAR +command 1>test 2>$VAR +command 1>|test 0>|$VAR + +# 3.6.3 Appending Redirected Output + +command >>test >>$VAR +command 2>>test 2>>$VAR + +# 3.6.4 Redirecting Standard Output and Standard Error + +command &>test >&test +command >test 2>&1 + +# 3.6.5 Appending Standard Output and Standard Error + +command &>>test + +# 3.6.7 Here Strings + +command <<< word +command <<< $VAR +command <<< $(V=1 command here) +command 1<<< word +command 1<<< "string"$'ansi''single' +command <<< "HERE STRING" + +for i in; do + if bla; then + while read -r; do + done <<< "HERE STRING" + fi +done + +# 3.6.8 Duplicating File Descriptors + +command <&1 +command 1<&1 +command 1<&$VAR +command 1<&- +command >&1 +command 2>&3 +command 1>&$VAR +command 1>&- + +# 3.6.9 Moving File Descriptors + +command <&1- +command 1<&1- +command >&1- +command 1>&1- + +# 3.6.10 Opening File Descriptors for Reading and Writing + +command <> test +command 1<>test + +# 4.1 Bourne Shell Builtins + +: a b c d +. file arg1 arg2 arg3 +break; break $VAR; break 1; break error here +cd; cd -L -e dir +continue; continue $VAR; continue 1; continue error here +eval a b c d +exec -c -a foo command a f g +exit; exit $VAR; exit 1; exit error here +export -fn -p VARNAME VAR="value" BASH CDPATH +getopts optstring NAME foo rrr ooo +hash -r -p name +pwd; pwd -L -P +readonly -aA VARNAME VAR="value" BASH IFS +return; return $VAR; return 1; return error here +shift; shift $VAR; shift 1; shift error here +test -x foo -o $ASD +[ -x foo -o $VAR ] +times; times error here +trap; trap -l -p a s df +umask -p -S 0444 +unset -f -n -v VAR1 VAR2 $VAR_IN_VAR CDPATH BASH + +# 4.2 Bash Builtin Commands + +alias; alias -p foo=bla +bind; bind -m aaa -f foo +builtin; builtin umask 0444 # <- should be as a command +caller; caller $VAR; caller 123 error here +command -pV grep here +declare -aA -p VAR1 VAR2=$FOO VAR3=$(command here) VAR4="str"'str'$'str' +echo -neE foo +enable -a -d fff +help -d patt +local -aA -p VAR1 VAR2=$FOO VAR3=$(command here) VAR4="str"'str'$'str' +logout; logout $VAR; logout 1; logout error here +mapfile -d 'f' file array +printf -v VAR 'format' foo +read -a -r VAR bla +readarray -d dd -C call array +source file; source file error here +type -af name +typeset -afFg VAR1 VAR2=$FOO VAR3=$(command here) VAR4="str"'str'$'str' +ulimit; ulimit -a; ulimit -H name +unalias; unalias -a; unalias name1 name2 + +let a=4 +let z=a++ +let y=--b +let result=~a +let "result=a<<2" +let "result=a&b" +let i=5 result=~a "result=a<<2" +let "myvar=7" "myvar2=4" "myvar3= myvar ^ myvar2" + +# 4.3.1 The Set Builtin + +set -a a b d + +# 4.3.2 The Shopt Builtin + +shopt -p -o opt + +# 5.2 Bash Variables + +$_ $BASH $BASHOPTS $BASHPID $BASH_ALIASES $BASH_ARGC +$BASH_ARGV $BASH_ARGV0 $BASH_CMDS $BASH_COMMAND $BASH_COMPAT $BASH_ENV +$BASH_EXECUTION_STRING $BASH_LINENO $BASH_LOADABLES_PATH $BASH_REMATCH +$BASH_SOURCE $BASH_SUBSHELL $BASH_VERSINFO $BASH_VERSION $BASH_XTRACEFD +$CHILD_MAX $COLUMNS $COMP_CWORD $COMP_LINE $COMP_POINT $COMP_TYPE $COMP_KEY +$COMP_WORDBREAKS $COMP_WORDS $COMPREPLY $COPROC $DIRSTACK $EMACS $ENV $EPOCHREALTIME +$EPOCHSECONDS $EUID $EXECIGNORE $FCEDIT $FIGNORE $FUNCNAME $FUNCNEST $GLOBIGNORE +$GROUPS $histchars $HISTCMD $HISTCONTROL $HISTFILE $HISTFILESIZE $HISTIGNORE +$HISTSIZE $HISTTIMEFORMAT $HOSTFILE $HOSTNAME $HOSTTYPE $IGNOREEOF $INPUTRC +$INSIDE_EMACS $LANG $LC_ALL $LC_COLLATE $LC_CTYPE $LC_MESSAGES $LC_NUMERIC +$LC_TIME $LINENO $LINES $MACHTYPE $MAILCHECK $MAPFILE $OLDPWD $OPTERR $OSTYPE +$PIPESTATUS $POSIXLY_CORRECT $PPID $PROMPT_COMMAND $PROMPT_DIRTRIM $PS0 $PS3 $PS4 +$PWD $RANDOM $READLINE_ARGUMENT $READLINE_LINE $READLINE_MARK $READLINE_POINT +$REPLY $SECONDS $SHELL $SHELLOPTS $SHLVL $SRANDOM $TIMEFORMAT $TMOUT $TMPDIR $UID + +${#BASH} + +BASH=1 BASH=somestring + +# Bash variables in for loop + +for CDPATH; do + foo +done + +for CDPATH in 1 2 3; do + foo +done + +# Bash variables in commands that take variable names + +export CDPATH CDPATH=123 +unset CDPATH + +# 6.1 Invoking Bash + +bash; bash -c fff + +# 6.7 Arrays + +ADD=() +ARR=("val1" "val2" value\$one "val3" $(command here; echo \)) $'ansi-str') +ARR+=("val1" "val2" "val3" $(command here; echo \)) $'ansi-str') +ARR=(["foo"]="val1" [$VAR $VAR2 \] $VAR3]="val2" [$(V=1 command)]="foo" ["str"'str'$'\rstr']="str"'str'$'\rstr' ) + +${!A[1]} ${!A["idx"]} + +ARR[1]="val" + +ARR["FOO"]="val" [sdfsdf] # '[sdfsdf]' is a command +ARR[$IDX]="val" +ADD[${IDX[0]}]="foo" # <- index as array element +ADD[${#IDX[@]}]="foo" # <- index as array element + +echo $A["foo"] # <- here is A["foo"] is not an array, it is "$A" and '["foo"]' +echo ${A["foo"]} # <- here is A["foo"] is an array + +A[$(echo bla)] # <- this should be the command 'A[bla]', not a variable/array +A[$(echo bla)]=1 command here foo # <- this should be an array assignment and a command + +A[fla echo 1]=1 # assignment +A[fla "echo]=" 1]=foo # assignment +echo ${A[fla "echo]=" 1]} # echo the assignment + +# Arrays + Shell Parameter Expansion + +${A[foo]:-word} ${A['sdf']:=word} ${A[1]:?word} ${A[fff]:+word} + +${A[foo]:0} ${A[$'bla']:0:10} ${A[$(command)]: -1} ${A[10]: -1:-10} +${A[1]:$(( ${#B} + 10 )):$(command here)} ${A[foo]:"10":$'\r\t10'} +${A[0]:7} ${A[0]:1:10} ${A[@]:1} ${A[*]:1} + +${#A[foo]} + +${A[1]#word} ${A[foo]##word} ${A['sdf']%word} ${A[$(test)]%%word} + +" ${A[1]#word} ${A[foo]##word} ${A['sdf']%word} ${A[$(test)]%%word} " # <- in double quoted strings + +${A[10]/pat/str} ${A[foo]//pat/str} ${A["a"]/#pat/str} ${A[0]/%pat/str} +${A[foo]/$(command)/`test`"dbl"$'ansi'} + +${A[10]^pat} ${A[foo]^^pat} ${A["bla bla"],pat} ${A[iii],,pat} +${A[0]^$(command here)} ${A[1],,`test`"sdfasdf"$'\r\t\e'} + +${A[0]@U} ${A[1]@u} ${A[foo]@L} ${A["bla"]@Q} ${A[1]@E} +${A[$'ansi']@P} ${A[$(command here)]@A} ${A[`command here`]@K} ${A[$VAR]@a} ${A[0]@k} + +# 6.8.1 Directory Stack Builtins + +dirs -c -l +N; dirs +popd; popd -n +pushd; pushd -n dir + +# 7.2 Job Control Builtins + +bg; bg 1 +fg; fg 1 error here +jobs; jobs -l 123 +kill; kill -l 1 +wait; wait -f 10 1 +disown; disown -a id $ID +suspend; suspend -f; suspend -f error here + +# 8.7 Programmable Completion Builtins + +compgen -o word +complete -a name name +compopt -o opt name + +# 9.2 Bash History Builtins + +fc; fc -e name +history; history 1; history -c diff --git a/hrc/test/shell/shell-posix-spec.sh b/hrc/test/shell/shell-posix-spec.sh new file mode 100644 index 00000000..0dd01775 --- /dev/null +++ b/hrc/test/shell/shell-posix-spec.sh @@ -0,0 +1,920 @@ +#!/bin/sh + +# ------------------------------------------------------------------------ +# POSIX doc: + +# 2.2 Quoting +\| \& \; \> \< \( \) \$ \` \\ \" \' no meaning +test for no meaning for new line \ + I_AM_NOT_VARIABLE=1 command \ + if doesn\'t work also + +# 2.2.2 Single-Quotes +'single quote string' 'escape does not \work here' + +# 2.2.3 Double-Quotes +double quoted "only these chars should be escaped \$, \`, \", \\, but \nothing \! else" + +# 2.4 Reserved Words +! command +# Everything is marked as errors, except 'in' +do elif else +elif +elif VAR=1 some command here >&1 +else +in +then +# the following words are in their blocks: +# case/esac if/fi for/done while/done until/done +# +# Special cases +# +# Only the first reserved word must be highlighted +do elif else +# + +# 2.5.2 Special Parameters +$@ $* $# $? $- $$ $0 +${@} ${*} ${#} ${?} ${-} ${$} ${0} + +# 2.5.3 Shell Variables +$ENV $HOME $IFS $LANG $LC_ALL $LC_COLLATE $LC_TYPE $LC_MESSAGES +$LINENO $NLSPATH $PATH $PPID $PS1 $PS2 $PS4 $PWD + +$PATH_SEPARATOR # <- this is not a shell variable + +${ENV} ${HOME} ${IFS} ${LANG} ${LC_ALL} ${LC_COLLATE} ${LC_TYPE} ${LC_MESSAGES} +${LINENO} ${NLSPATH} ${PATH} ${PPID} ${PS1} ${PS2} ${PS4} ${PWD} + +ENV=1 HOME=2 IFS=3 LANG=foo LC_ALL=bar LC_COLLATE=xxx LC_TYPE=1 LC_MESSAGES=2 +LINENO=1 NLSPATH=bla PATH=11 PPID=r PS1=x PS2=+ PS4=e PWD=5 + +# 2.6.2 Parameter Expansion +${ASD-fo br} ${ASD:-fo" br"} ${ASD='br bz'} ${ASD:=br \{ bo} +${ASD?$VARH} ${ASD:?"$QVAR"} ${ASD+$(V=1 cmd re)} ${ASD:+`V=1 a here`} +${1-foo bar} ${1:-foo" bar"} ${1='bar baz'} ${1:=bar \{ boo} +${1?$VARHERE} ${1:?"$QVAR"} ${1+$(V=1 cmd here)} ${1:+`V=1 a here`} + +${#ASD} ${#1} + +${ASD%fo ba} ${ASD%%fo" br"} ${ASD#'bz bz'} ${ASD##br \{ bo} +${1%$VARH} ${1%%"$QVAR"} ${1#$(V=1 cmd re)} ${1##`V=1 a here`} + +$ASD $1 + +# Word break characters should not be considered as the end of +# the parameter extension. + +${A%foo # bar} +${A%foo ; command} +${A%foo > command} +${A%foo ) command} +${A%foo ( command} +${A%foo & command} +${A%foo | command} + +A=123 A="sdfasdf" A=$(V=1 command here 2>/dev/null) B=`cd asd` +A=123; cd test +A=1|B=2|topipe command +A=1;nextcmd +A=1>A=1 cmd here # <- 'A=1' is not a variable assignment, it is a file + +# 2.6.3 Command Substitution +exec 1 $( { V=123 V2="sdsdf"; }; execute something 2>&1 1>/dev/null && X=1 echo 123 V=1) +exec 2 "$(V=123 V2="sdsdf" execute something 2>&1 1>/dev/null && X=1 echo 123 V=1)" +exec 3 `V=123 V2="sdsdf" execute something 2>&1 1>/dev/null && X=1 echo 123 V=1` +exec 4 "`V=123 V2="sdsdf" execute something 2>&1 1>/dev/null && X=1 echo 123 V=1`" + +# nested (not implemented, TODO?) +exec 3 `V=123 V2="sdsdf" \`X=1 echo 123 V=1\` more params` +exec 4 "`V=123 V2="sdsdf" \`X=1 echo 123 V=1\` more params`" + +# 2.6.4 Arithmetic Expansion +$(( X + B << 2 * 10 / 30 + $X - $1 % "123" )) +A=$(( X + B << 2 * 10 / 30 )) +A="$(( X + B << 2 * 10 / 30 ))" + +# 2.7.1 Redirecting Input +foo < bla +foo 0< bla + +# 2.7.2 Redirecting Output +foo > bla +foo 2>bla +foo 2>|bla + +# 2.7.3 Appending Redirected Output +foo >> bla +foo 2>>bla + +# 2.7.4 Here-Document +Non quoted here-doc 2</dev/null), +and $((arithmetic expansion + 1 / 10)). In this case, the in the input +behaves as the inside double-quotes (see Double-Quotes). +( Here we are \$, \`, \", \\, but \nothing \! else ) +However, the double-quote character ( ' )' shall not be treated specially +within a here-document, except when the double-quote appears +within "$()", "``", or "${}". (WTF?!) +BLA + +Quoted here-doc <<-"FOO" +If any part of word is quoted, the delimiter shall be formed by performing +quote removal on word, and the here-document lines $shall not be $(expanded). +FOO + +Single-quoted here-doc <<'FOO' +not $expanded +FOO + +heredoc after redirection >foobar << BLA +with space before label +BLA + +# 2.7.5 Duplicating an Input File Descriptor +1<&2 <&- + +# 2.7.6 Duplicating an Output File Descriptor +1>&2 2>&- + +# 2.7.7 Open File Descriptors for Reading and Writing +<>/blabla 1<> /blabla + +# 2.9.1 Simple Commands / Command Search and Execution / builtin +# The command must be on the first place +alias foo=bla +bg alias cd +cd command A1=11 +DEFINE_VAR=1 command +false +DEFINEVAR=2 command cd alias >/dev/null +DEFVAR=1 fc 1>&1 +fg +getopts more parameters here +hash THIS_IS_PARAMETER_BUT_NOT_VARIABLE=1 +jobs +kill +newgrp +pwd +read +true +umask +unalias +wait while do for in +# +# Special cases: +# +# Only the first buildin command must be highlighted +alias bg cd hash +# variables after buildin command must not be highlighted as are plain parameters +# however, variables after reserved words must be highlighted +alias VAR1=1 +# reserved words must not be highlighted after builtin command +command while something; command + +# 2.9.2 Pipelines +VAR1=1 foo bla | VAR=2 ! test cmd # exclamation mark is NOT highlighted + +# 2.9.3 Lists +VAR1=1 foo bla && ! VAR=2 test cmd || VAR=3 command read # exclamation mark is highlighted +VAR=1 foo & && VAR=2 test cmd +R=1 date && V=1 who || VAR=1 ls; VAR=2 cat file +V=1 wc file > output & R=1 true +# Asynchronous Lists +V=1 background1 & V=2 background2 +# Sequential Lists +V=1 command1; V=2 command2 + +# 2.9.4 Compound Commands +( V1=1 grouped command1; V=1 command2 ) +( + V1=1 command1 here + V2=2 command2 + ( + V2= nested + { + V3=1 nested + } + ) +) +( V1=1 command1 +V2=2 command2 \) ) + +{ V1=1 group 1; V1= command2 here should be an error here because of the missing semicolon } +} # this one works +{ cmd1; cmd2; no error here; } +{ + cmd1 + V1=cmd1 + { + nested + \} + } +} + +if +fi # <- error here, there is no 'then' +then +fi # <- close the above 'if' + +# The for Loop + +for IFS in 1 2 3 # comment here +do +done + +for IFS in $(V1=val command) 2 3; do command; done; # check special variable +for "IFS" in $(V1=val command) 2 3; do command; done; # check variable in quotes + +for var in $VAR; do + +done + +for var in; error here do done +do +done + +for var in; error here; do done + +for var in; do done + +for VAR in "BLA" "FOO" "BAR"; do; done + +for VAR # comment here +do +done + +for $(V1=val command here); do + command +done + +for VAR error here; do +done + +for VAR; do + command + if [ -n "$FOO" ]; then + something + fi +done + +for IFS; do command; done; # check special variable + +for "IFS"; do command; done; # variable in quotes <- 'in' word must not activate the 'in' syntax for form +for "IFS"; do command; done; # variable _in quotes + +# Case Conditional Construct + +case $FOO in +a aaaaa pat1) A=1 xdo; A=2 something ;; + pat2|fff\) BLA=123) B=2;; + pat3) + A=x cmd;; + pat4) + B=1 cmd + C=3 cmd1 + if [ -x "$BLA" ]; then + ffff + case $BLA in + fff) F=1;; + bla) no the last ";;" here + esac + fi + ;; +here pat) T=1 ttt;; + $VAR_HERE) cmd;; + $(V1=1 some command here)) cmd2;; + *) bla + fooo + ;; +esac + +# The if Conditional Construct + +if foo; then + C=1 cmd here 2>/dev/null +fi + +if [ $BLABLA -gt 1 ]; then VAR=HERE cd blalbla; fi + +if [ -x "$N" ]; then + alias skdfjlkj +elif V=1 some command here; then + V1=1 anything here + blalba +elif [ -t -o 1 -x ]; then + X=1 ffff +else + command here +fi + +if [ $BLABLA != "123" ]; then + X=1 somecmd sfasfasd sfsfasdf afa sdf sdf; + if foo; then + cd sdfkjkjfkj + fi +fi + +if V=1 command here +then + V1=2 we do something + if nested; then + nothing to do + fi +fi + +# The while Loop + +while true; do + something +done + +while [ -x "$BLA" ]; do something here; done +while [ -x "FOO" ]; do while bla; do nothing; done; done + +while x 2>&1; do + while nested; do + nothing + done +done + +# The until Loop + +until true; do + something +done + +until [ -x "$BLA" ]; do something here; done + +until x 2>&1; do + while nested; do + until [ -x nested ]; do + nothing + done + done +done + +# 2.9.5 Function Definition Command + +somefn() sfkjskdfj; +no fn here + +somefn () { + still fn + bla + fnd2() { + another fn + } +} + +somefn() + +errorfn() { blalbla } +close the curved bracket from above; } + +func( ) cmd function with space between brackets +func ( ) cmd function with space between brackets#2 + +# 2.14. Special Built-In Utilities + +# NAME +# break - exit from for, while, or until loop +# SYNOPSIS +# break [n] + +break +break; break; break +break 10 +break "$VAR"; break '123' +break a10 # <- errors here +break; break 10; break error here; break 1; # the last is ok +break error here +break; # this is ok +break $SOMEVAR but error here +break $(V=1 eval something here) but error here + +# NAME +# colon - null utility +# SYNOPSIS +# : [argument...] + +: +: highlight only $VAR here and $(V=1 evaluations) + +# NAME +# continue - continue for, while, or until loop +# SYNOPSIS +# continue [n] + +continue +continue; continue; continue 10 20 # second parameter is an error +continue 10 +continue a10 # <- errors here +continue; continue 10; continue error here; continue 1; # the last is ok +continue error here +continue; # this is ok +continue $SOMEVAR but error here +continue $(V=1 eval something here) but error here + +# NAME +# dot - execute commands in the current environment +# SYNOPSIS +# . file + +. file; . tttt +. file 2>/dev/null error here; +. file; . file $VAR error here; command next here +. file; . file error here # comment here + +# NAME +# eval - construct command by concatenating arguments +# SYNOPSIS +# eval [argument...] + +eval "something" 2>/dev/null +eval "something" +eval "one" "two" $(V1=1 cmd3 >/dev/null) +eval; V=1 another command here +eval ; V=1 another command here +eval # comment here + +# NAME +# exec - execute commands and open, close, or copy file descriptors +# SYNOPSIS +# exec [command [argument...]] + +exec command is not highlighted as buildin 1>/dev/null +exec; V1=1 command here +exec ; V1=1 command here too +exec 3< readfile +exec 4> writefile +exec 5<&0 +exec 3<&- +foo=bar exec cmd + +# NAME +# exit - cause the shell to exit +# SYNOPSIS +# exit [n] + +exit +exit; exit; exit +exit 10 +exit a10 # <- errors here +exit; exit 10; exit error here; exit 1; # the last is ok +exit error here +exit; # this is ok +exit $SOMEVAR but error here +exit $(V=1 eval something here) but error here + +# NAME +# export - set the export attribute for variables +# SYNOPSIS +# export name[=word]... +# export -p + +export ; export VAR FOO BLA=1 PATH $IFS PATH=123 -wrong variable name +export X="fff" R="$(V=1 cmd here)" $VAR_ALSO 'quoted' 1wrong variable name +export -p; export only; #comment here +export -p a # <- error here +export -p error here; export VAR one two +export X=$(false) + +# NAME +# readonly - set the readonly attribute for variables +# SYNOPSIS +# readonly name[=word]... +# readonly -p + +readonly +readonly 1>/a123 FFF # <- error here +readonly DFF 1>/b123 +readonly; readonly VAR FOO BLA=1 PATH $IFS PATH=123 -wrong variable name +readonly X="fff" R="$(V=1 cmd here)" $VAR_ALSO 'quoted' 1wrong variable name +readonly -p; readonly only; #comment here +readonly -p a # comment here +readonly -p error here; readonly VAR one two +readonly X=$(false) + +# NAME +# return - return from a function or dot script +# SYNOPSIS +# return [n] + +return +return 2>/dev/null error here +return 10 2>/dev/null error here +return; return; return +return 10 +return a10 <- errors here +return; return 10; return error here; return 1; # the last is ok +return error here +return; # this is ok +return $SOMEVAR but error here +return $(V=1 eval something here) but error here + +# NAME +# set - set or unset options and positional parameters +# SYNOPSIS +# set [-abCefhmnuvx] [-o option] [argument...] +# set [+abCefhmnuvx] [+o option] [argument...] +# set -- [argument...] +# set -o +# set +o + +set +set; set +a 1>/dev/null +set -o option $(cmd here); set -- "$VAR" +set -o +set +o + +# NAME +# shift - shift positional parameters +# SYNOPSIS +# shift [n] + +shift +shift 2>/dev/null error here +shift; shift; shift +shift 10 +shift a10 <- errors here +shift; shift 10; shift error here; shift 1; # the last is ok +shift error here +shift; # this is ok +shift $SOMEVAR but error here +shift $(V=1 eval something here) but error here + +# NAME +# times - write process times +# SYNOPSIS +# times + +times; times error here; #comment here +times aaa # comment here +times error here; times 2>/dev/null sdfsdfasf + +# NAME +# trap - trap signals +# SYNOPSIS +# trap n [condition...] +# trap [action condition...] + +trap 1 SIG1 SIG2 $SIG_AS_VARIABLE $(command here) +trap "some sction" SIG1 SIG2 2>/dev/null; V=1 the next command here +trap 1 1>/dev/null + +# NAME +# unset - unset values and attributes of variables and functions +# SYNOPSIS +# unset [-fv] name... + +unset -x; #<- error here +unset; +unset -f; unset -v; unset -fv; unset -vf +unset -f VAR VAR2; unset -v VAR VAR2; unset -vf VAR VAR ERR_HERE=1 +unset VAR VAR2 IFS VAR3 $(V=1 cmd here) "quote" 'single' 2>/dev/null +unset VAR=234 FFFgger; # <- error here, no assignments + +# 4. Utilities + +# Special cases + +test -x /some/file -o -n "$BLABLA" && test -n "$VAR" + +batch; batch error hereas; batch $(AGAIN ERROR) fasdf # comment here + +false; false error here; #comment + +true; true error here; #comment + +logname; logname error here; #comment + +sleep; sleep 10; sleep $VAR; sleep a10 # <- error here + +tty; tty error here; #comment + +dirname; dirname $A; dirname test error here ;# comment +dirname $VAR error here; dirname foo + +uname; uname -a; #comment here +uname -a error here + +# Common cases + +alias; +alias name; alias name='string' # comment here +alias name=$FOO; # comment here +ar -x; ar -r; #comment here +ar +ar; ar -p +at -l -1 bla; at; at -m '10' $(V1=1 cmd run) +awk; awk -F bla; awk $(TE=1 cmd) # comment here +basename; basename bla; basename $(TE=1 cmd) # comment here +bc; bc -l; bc foo $(V1=1 cmd) $VAR_HERE; # comment +bg; bg $ID; #comment here +cal 1 2020; cal; cal 1 $(C1=1 cmd here); #comment +cat; cat -u; cat /some/file; cat $FROM_VAR; # comment +cd -; cd /foo/bar; cd -L; # comment +chgrp; chgrp -h ${GROUP} /some/file; # comment +chmod; chmod -R 0666 /some/file; chmod -R; # comment +chown; chown -h root:root /some/file; chown -R; # comment +cksum; cksum /file; cksum ${VAR}; # comment +cmp; cmp -l; cmp file1 file2; # comment +comm; comm -1 file1 file2; comm $(V=1 cmd here); # comment +command some command here; command cd $FOO; #comment +compress; compress -c file; #comment +cp; cp a b; #comment +crontab; crontab file; #comment +csplit; csplit -k file; #comment +cut; cut -d1 -f; #comment +date; date +Z; # comment +dd; dd if=bla; #comment +df; df -m; # comment +diff; diff -r ba br; #comment +du; du foo; # comment +echo; echo "$SOMETHING"; #comment here +ed; ed bbbb; # comment +env; env foo; #comment +ex; ex file; #comment +expand; expand foo; #comment +expr; expr $A + 1; #comment +fc; fc -l; #comment here +fg; fg $ID; #comment here +file; file /dev/$FILE; #comment +find; find -x $XXX; #comment +fold; fold -bs /some/file; #comment +fuser; fuser -c /some/file; #comment +getconf; getconf $VAR; #comment +getopts; getopts "$VAR"; #comment +grep; grep blalba $VAR; #comment +hash; hash $FOO; #comment +head; head -n 1; head /file/$VAR; #comment +iconv; iconv -f bla -t foo; #comment +id; id -a; id $USER; #comment +ipcrm; ipcrm -q $ID; #comment +ipcs; ipcs -q $VAR; #comment +jobs; jobs -l; #comment +join; join -a $VAR; #comment +kill; kill -9 #ID; #comment +link; link file $VAR; #comment +ln; ln -s /ffff $VAR; #comment +locale; locale -a $VAR; #comment +localedef; localedef -a; #comment +logger; logger -a; #comment +ls; ls -a /foo; #comment here +mailx; mailx $FOO; #comment here +make; make -f makefile; # comment here +man; man foo; #comment here +mesg; mesg --option; #comment here +mkdir; mkdir -p; #comment here +mkfifo; mkfifo $FOO; #comment here +more; more $FOO; #comment here +mv; mv -f foo bla; #comment here +newgrp; newgrp -n $VAR; #comment here +nice; nice -c 1; #comment here +nl; nl $FOO; # comment here +nm; nm $FOO; #comment here +nohup; nohup test; #comment here +od; od $FOO; # comment here +paste; paste /from/file; #comment here +patch; patch -p0 /patch/file; #comment here +pathchk; pathchk $FOO; #comment here +pr; pr $FOO; #comment here +printf; printf -v BLA 'STRING'; #comment here +ps; ps -a; #comment here +pwd; pwd -L; #comment here +read; read -r VAR; #comment here +renice; renice -a; #comment here +rm; rm -rf; #comment here +rmdir; rmdir /test; #comment here +sed; sed -i $VAR; #comment here +sh; sh -c $FOO; #comment here +sort; sort $FOO; #comment here +split; split $FOO; #comment here +strings; strings /some/file; #comment here +strip; strip $FOO; #comment here +stty; stty -a; #comment here +tabs; tabs -t; #comment here +tail; tail -f /foo; #comment here +tee; tee /foo/bar; #comment here +time; time -a $VAR; #comment here +touch; touch $FOO; #comment here +tput; tput $FOO; #comment here +tr; tr 'ff' 'bbb'; #comment here +tsort; tsort $FILE; #comment here +type; type -p; #comment here +ulimit; ulimit -t; #comment here +umask; umask 0444; #comment here +unalias; unalias -a; #comment here +uncompress; uncompress $FOO; #comment here +unexpand; unexpand $FOO; #comment here +uniq; uniq --help; #comment here +unlink; unlink $FILE; #comment here +vi; vi $FILE; #comment here +wait; wait $PID1 $PID2; #comment here +wc; wc -l; wc $FILE; #comment here +who; who -a; who am i; #comment here +write; write $TEST; #comment here +xargs; xargs $FOO $BLA; #comment here +zcat; zcat $FILE; #comment here + +# The usual chunks of code from: +# https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html + +a=1 +set 2 +echo ${a}b-$ab-${1}0-${10}-$10 + +foo=asdf +echo ${foo-bar}xyz} + +${x:-$(ls)} + +unset X +echo ${X:=abc} + +unset posix +echo ${posix:?} + +set a b c +echo ${3:+posix} + +HOME=/usr/posix +echo ${#HOME} + +x=file.c +echo ${x%.c}.o + +x=posix/src/std +echo ${x%%/*} + +x=$HOME/src/cmd +echo ${x#$HOME} + +x=/one/two/three +echo ${x##*/} + +"${x#*}" + +${x#"*"} + +# repeat a command 100 times +x=100 +while [ $x -gt 0 ] +do + command + x=$(($x-1)) +done + +# nested heredocs are not supported +#cat < /some/file +Hi, +eof1 +Helene. +eof2 + +false && echo foo || echo bar +true || echo foo && echo bar + +while + # a couple of s + + + # a list + date && who || ls; cat file + # a couple of s + + + # another list + wc file > output & true + + +do + # 2 lists + ls + cat file +done + +for i in * +do + if test -d "$i" + then break + fi +done + +foo() { + for j in 1 2; do + echo 'break 2' >/tmp/do_break + echo " sourcing /tmp/do_break ($j)..." + # the behavior of the break from running the following command + # results in unspecified behavior: + . /tmp/do_break + + + do_continue() { continue 2; } + echo " running do_continue ($j)..." + # the behavior of the continue in the following function call + # results in unspecified behavior (if execution reaches this + # point): + do_continue + + + trap 'continue 2' USR1 + echo " sending SIGUSR1 to self ($j)..." + # the behavior of the continue in the trap invoked from the + # following signal results in unspecified behavior (if + # execution reaches this point): + kill -s USR1 $$ + sleep 1 + done +} +for i in 1 2; do + echo "running foo ($i)..." + foo +done + +: ${X=abc} +if false +then : +else echo $X +fi + +x=y : > z + +for i in * +do + if test -d "$i" + then continue + fi + printf '"%s" is not a directory.\n' "$i" +done + +cat foobar +. ./foobar +echo $foo $ba + +eval " $commands" +eval " $(some_command)" +foo=10 x=foo +y='$'$x +echo $y +eval y='$'$x +echo $y + +exec 3< readfile +exec 4> writefile +exec 5<&0 +exec 3<&- +exec cat maggie +foo=bar exec cmd + +exit 0 +exit 1 +( + command1 || exit 1 + command2 || exit 1 + exec command3 +) > outputfile || exit 1 +echo "outputfile created successfully" + +export X=$(false) +X=$(false) +export X + +export PWD HOME +export PATH=/local/bin:$PATH +export -p > temp-file +unset a lot of variables + +set -e +start() { + some_server + echo some_server started successfully +} +start || echo >&2 some_server failed +set +set c a b +set -xv +set -- +set -- "$x" +set -- $x +set -- "$@" + +trap "jobs -n" CLD + +set a b c d e +shift 2 +echo $* + +save_traps=$(trap) +eval "$save_traps" + +trap '"$HOME"/logout' EXIT +trap '"$HOME"/logout' 0 +trap - INT QUIT TERM EXIT + +trap 'read foo; echo "-$foo-"' 0 +trap 'eval " $cmd"' 0 +trap " $cmd" 0 diff --git a/hrc/test/other/test.sh b/hrc/test/shell/test.sh similarity index 100% rename from hrc/test/other/test.sh rename to hrc/test/shell/test.sh