echo ${(#):-65}
will show you the Latin letter “A”. Works with current locale. In principle, this is enough for writing the necessary program, but there are other knowledge that greatly facilitate life:+
), and you can also get an additional array @
(and not one, but only one in one scope).man zshexpn
, more details in the ARITHMETIC EVALUATION section in man zshmisc ), which eliminates the spelling of $(())
, $[]
, yes and just $
. Including the example above can be written as V=0x41; echo ${(#):-V+(VV)}
V=0x41; echo ${(#):-V+(VV)}
, which also applies to values within indices (useful when using $@
).${(#)}
can be done with an array, with (#)
applied to each element of the array.${${(#)@}// }
quite successfully converts the array of arithmetic expressions given in the arguments into one line without spaces (two transformations : (#)
and removal of spaces). You do not need a temporary variable for the transformations above the lines: ${:-string}
expanded in string
, although there are no variables here (the variant was used above). Bash and in general all other shells cannot do this. 1 (){__=$# } !;___=$[__<<__];____=$[__<<___];_____=$((___<<___)) 2 _______=$((__+(__<<(__+____))+(__<<(__+____))<<(__+____))) 3 ______=$((_______+__+__<<____)) 4 \*(){(( ${@[-__]} < ______+(______-_______)+_____ )) && { <<< $@ ; <<< $(\* $[$@+____]) } } 5 +(){<<< "${${(#)@}// }"} 6 (){ 7 (){<<< "$@"} \ 8 "$(+ _______)" \ 9 "$(+ ${@[____]}-__ ${@[____]} ______ ${@[-__]}+__ ${@[____]}-___)" \ 10 "$(+ ${@[__]}+__ ${@[____]} ${@[__]}+___ ${@[____]} ${@[____]}-___ '____<<(____-__)+__')" \ 11 } $(\* $[______])
. Here in the first line we declare variables with the values 1, 2, 4, 8, in the second with the value 0x0421 (U + 0421 is the CYRILLIC CAPITAL LETTER ES), in the third - 0x0432 (CYRILLIC SMALL LETTER VE). In the fourth line, the recursive function that generates a sequence of numbers in increments of 4, in the fifth line, the function practically considered above turns the array of arithmetic expressions into a string without spaces. env -i PATH= LANG=ru_RU.UTF-8 /bin/zsh -f script.zsh *: command not found: cat *: command not found: cat *: command not found: cat *: command not found: cat *: command not found: cat *: command not found: cat *: command not found: cat *: command not found: cat *: command not found: cat *: command not found: cat *: command not found: cat *: command not found: cat *: command not found: cat *: command not found: cat +: command not found: cat +: command not found: cat +: command not found: cat (anon): command not found: cat
. Oh, something is wrong here: there is a violation of the first condition. It's all about $NULLCMD
: when there is no command, and we use redirection, the value of this variable is implicitly substituted, the default is cat
. The solution is to create a cat
function: cat() while { read i } { echo $i }
(yes, the definition of a function without braces is correct, as is the loop with them, but without do
/ done
). Without eval
this cannot be done, so the string being executed must be of the form eval 'cat()while {read i} {echo $i}'
. A small problem here is that <<<
can not be used, so you can not bother, but simply rewrite everything with another variable or function containing / returning echo
. In the final program, this is the @
function: (){__=$# } !;___=$[__<<__];____=$[__<<___];_____=$((___<<___)) ______=$[_____<<____-___<<____+____] ________="${(#):-______+__}${(#):-______-__}${(#):-______+____}${(#):-______+_____+___+__}" @() $________ $________ _______=$((__+(__<<(__+____))+(__<<(__+____))<<(__+____))) ______=$((_______+__+__<<____)) \*(){(( ${@[-__]} < ______+(______-_______)+_____ )) && { $(@) $@ ; $(@) $(\* $[$@+____]) } } +() $(@) "${${(#)@}// }" (){ (){$(@) "$@"} \ "$(+ _______)" \ "$(+ ${@[____]}-__ ${@[____]} ______ ${@[-__]}+__ ${@[____]}-___)" \ "$(+ ${@[__]}+__ ${@[____]} ${@[__]}+___ ${@[____]} ${@[____]}-___ '____<<(____-__)+__')" } $(\* $[______])
The penultimate step will get rid of quotes where you can: (){__=$# } !;___=$[__<<__];____=$[__<<___];_____=$((___<<___)) ______=$[_____<<____-___<<____+____] ________=${(#):-______+__}${(#):-______-__}${(#):-______+____}${(#):-______+_____+___+__} @() $________ $________ _______=$((__+(__<<(__+____))+(__<<(__+____))<<(__+____))) ______=$((_______+__+__<<____)) \*(){(( ${@[-__]} < ______+(______-_______)+_____ )) && { $(@) $@ ; $(@) $(\* $[$@+____]) } } +() $(@) "${${(#)@}// }" (){ (){$(@) $@} \ $(+ _______) \ $(+ ${@[____]}-__ ${@[____]} ______ ${@[-__]}+__ ${@[____]}-___) \ $(+ ${@[__]}+__ ${@[____]} ${@[__]}+___ ${@[____]} ${@[____]}-___ '____<<(____-__)+__') } $(\* $[______])
Minor minification, but something code painfully clear: (){__=$# } !;___=$[__<<__];____=$[__<<___];_____=$[___<<___] ______=$[_____<<____-___<<____+____] ________=${(#):-______+__}${(#):-______-__}${(#):-______+____}${(#):-______+_____+___+__} @()$________ $________ _______=$[__+(__<<(__+____))+(__<<(__+____))<<(__+____)] ______=$[_______+__+__<<____] \*(){((${@[-__]}<______+(______-_______)+_____))&&{`@` $@ `\* $[$@+____]` }} +()`@` "${${(#)@}// }" (){(){`@` $@} `+ _______` `+ ${@[____]}-__ ${@[____]} ______ ${@[-__]}+__ ${@[____]}-___` `+ ${@[__]}+__ ${@[____]} ${@[__]}+___ ${@[____]} ${@[____]}-___ '____<<(____-__)+__'` } `\* $[______]`
. Start, I will remind, env -i PATH= LANG=ru_RU.UTF-8 /bin/zsh -f script.zsh
.eval LANG=C
, and with this locale, ${(#)}
produces bytes with the specified value): (){__=$# } !;___=$[__<<__];____=$[__<<___];_____=$[___<<___] ______=$[_____<<____-___<<____+____] ________=${(#):-______+__}${(#):-______-__}${(#):-______+____}${(#):-______+_____+___+__} @()$________ $________ ^()`@` ${(#):-$@[__]}${(#):-$@[___]} ''(){(($@<(_____<<____)))&&`@` ${(#)@}||^ $[($@)>>(____+___)|(_____<<____+_____<<(___+__))] $[($@)&(__<<(____+___)-__)|(_____<<____)]} _______=$[__+(__<<(__+____))+(__<<(__+____))<<(__+____)] ______=$[_______+__+__<<____] \*(){((${@[-__]}<${@[__]}))&&{`@` $[$@[-__]] `\* $@[__] $[$@[___]+____]` }} +(){(($#))&&`@` $('' $@[__])$(+ $@[___,-__])} /()`@` "${${(#)@}// }" `() {/ $@[__] $@[-__]+____+__ $@[__]-____ $@[-___]-__} $(\* $[#________+(_____<<__)] $[#________])` \ `() {/ $@[-__] $@[__]+__ $@[-__]+___ $@[___+__]-__} $(\* '(____<<____)+_____*___' '____<<____')`=${(#):-$[_____<<(___+__)+___+__]} (){(){`@` $@} `+ _______` `+ ${@[____]}-__ ${@[____]} ______ ${@[-__]}+__ ${@[____]}-___` `+ ${@[__]}+__ ${@[____]} ${@[__]}+___ ${@[____]} ${@[____]}-___ '____<<(____-__)+__'` } `\* '______+(______-_______)+_____' ______`
.$?
variable $?
. &>‐
this prevents the error message from being printed: the /()+++++++&>-
function /()+++++++&>-
equivalent to ?=127
(if, of course, you could assign this variable) unless you do not have the +++++++
command +++++++
. ${#?}
will then be equal to three. Also, you can use /()''&>-
: will this option always give you 126
in $?
since you cannot execute a directory (note: you can define a function with an empty name, which makes it impossible to use this trick). The last trick: the /(). /().&>-
function /().&>-
$?
1, as there is an attempt to call .
without arguments, a /(). ''&>-
/(). ''&>-
because .
will try to find a file with an empty name in $PATH
, and, of course, will not (if you add a file to $PATH
instead of a directory, you will receive the same return code with the message “This is not a directory”:. looking for path_item/
, and having /
in the end leads to this result).$!
contains the PID of the last process running in the background. Or 0, if nothing in the background was launched (although the last part is not described in the documentation).${base}#${number}
, which makes the task just elementary to generate: in $!
we have 0, in $@
we have an array of one element (1), the number is collected in the form $[$@+$@]#$@$!$!$!
will collect 2#1000
or 8
. If you don’t want to generate for any reason, then anonymous functions come in with the ability to assign $@
values you need. Here is an example of code that performs eval LANG=C
: /()+++&>- //()''&>- ///().&>- () { () { / () { / () { / ${(#):-$@[${##}<<${##}]+${##}}${(#):-$@[$#]+${##}<<${#?}}${(#):-$@[${#}-${##}]-${#?}}${(#):-$@[$#]-${##}-${##}} $@[${##}] } $@[${##}] ${##}$!$! $[${##}$!$!+${##}$!] } ${(#):-$@[$#]+${?[-${##}]}-${##}}${(#):-$@[${#}-${##}]+${?[${##}]}+${##}<<${?[${##}+${##}]}}${(#):-$@[$#]+${##}<<${#?}}${(#):-$@[$#]+${##}}=${(#):-$@[$#]-${#?}} $@[${##},${#?}] } $@ $[$@[$#]+${#}-${##}]$! $[$@[$#]+${#}]$! } ${#?} $[${#?}+${#?}] $[${#?}<<(${#?}+${#?})]
echo !
: #!/usr/bin/env python3.4 print(''.join( ( ' ' if i == next(iter(b' ')) else '${{(#):-$[$[$@+$@]#{:b}]}}'.format(i).replace('0', '$!').replace('1', '$@') ) for i in 'echo !'.encode('utf8')))
echo !
and manually assembling eval LANG=C
: /()+++&>- //()''&>- ///(). ''&>- () { () { / () { / () { / ${(#):-$@[${##}<<${##}]+${##}}${(#):-$@[$#]+${##}<<${#?}}${(#):-$@[${#}-${##}]-${#?}}${(#):-$@[$#]-${##}-${##}} $@[${##}] } $@[${##}] ${##}$!$! $[${##}$!$!+${##}$!] } ${(#):-$@[$#]+${?[-${##}]}-${##}}${(#):-$@[${#}-${##}]+${?[${##}]}+${##}<<${?[${##}+${##}]}}${(#):-$@[$#]+${##}<<${#?}}${(#):-$@[$#]+${##}}=${(#):-$@[$#]-${#?}} $@[${##},${#?}] } $@ $[$@[$#]+${#}-${##}]$! $[$@[$#]+${#}]$! } ${#?} $[${#?}+${#?}] $[${#?}<<(${#?}+${#?})] : () { ${(#):-$[$[$@+$@]#$@$@$!$!$@$!$@]}${(#):-$[$[$@+$@]#$@$@$!$!$!$@$@]}${(#):-$[$[$@+$@]#$@$@$!$@$!$!$!]}${(#):-$[$[$@+$@]#$@$@$!$@$@$@$@]} ${(#):-$[$[$@+$@]#$@$@$!$@$!$!$!$!]}${(#):-$[$[$@+$@]#$@$!$@$!$!$!$!$@]} ${(#):-$[$[$@+$@]#$@$@$!$@$!$!$!$!]}${(#):-$[$[$@+$@]#$@$!$@$@$@$@$!$@]}${(#):-$[$[$@+$@]#$@$@$!$@$!$!$!$!]}${(#):-$[$[$@+$@]#$@$!$@$@$@$@$@$!]}${(#):-$[$[$@+$@]#$@$@$!$@$!$!$!$!]}${(#):-$[$[$@+$@]#$@$!$@$@$!$!$@$!]}${(#):-$[$[$@+$@]#$@$@$!$@$!$!$!$@]}${(#):-$[$[$@+$@]#$@$!$!$!$@$!$@$@]}${(#):-$[$[$@+$@]#$@$@$!$@$!$!$!$!]}${(#):-$[$[$@+$@]#$@$!$@$@$@$@$!$!]} ${(#):-$[$[$@+$@]#$@$@$!$@$!$!$!$!]}${(#):-$[$[$@+$@]#$@$!$@$@$!$!$@$@]}${(#):-$[$[$@+$@]#$@$@$!$@$!$!$!$!]}${(#):-$[$[$@+$@]#$@$!$@$@$@$@$@$!]}${(#):-$[$[$@+$@]#$@$@$!$@$!$!$!$!]}${(#):-$[$[$@+$@]#$@$!$@$@$!$@$!$!]}${(#):-$[$[$@+$@]#$@$@$!$@$!$!$!$!]}${(#):-$[$[$@+$@]#$@$!$@$@$@$@$@$!]}${(#):-$[$[$@+$@]#$@$@$!$@$!$!$!$!]}${(#):-$[$[$@+$@]#$@$!$@$@$@$@$!$!]}${(#):-$[$[$@+$@]#$@$!$!$!$!$@]} } ${#?}
:
need to be guaranteed to have 0
in $?
). If you run strace
, you will see that there is still a fork
: when you start /
, fork
is done first, and then you can get over the possible locations of +++
. The same will come out with a ''
, so you need to replace the function /
with ///
, which gives exactly the same result as /
(not //
!), But without fork
.Source: https://habr.com/ru/post/247249/
All Articles