HP-UX KSH scripting - passing blank parameters with $# - unix

I have a 'problem' with a script I'm developing in HP-UX KSH. The script contains many functions, and I need to pass the same set of parameters between them. All well and good, but some parameters can be blank. Its easy to pass blank parameters using double double-quotes (""), but what if I want to pass a complete set of parameters from one function into another using ${#}, including blanks? And to make things tricky, there can be a variable number of parameters each time, so the method has to be dynamic.
Example: I've got a function called test1 that takes a number of parameters. Any of them can be blank. I've also created a function called test2 into which all the parameters of test1 are passed:
test1()
{
echo 1-1: ${1}
echo 1-2: ${2}
test2 ${#}
}
test2()
{
echo 2-1: ${1}
echo 2-2: ${2}
}
# test1 "" hello
1-1:
1-2: hello
2-1: hello
2-2:
The trouble is, if ${1} is blank, ${2} from test1 appears as ${1} in test2. So to work around the problem I created this code, which effectively creates a function string with all parameters surrounded with double quotes:
test1()
{
typeset var FUNC="test2"
typeset -i var COUNT=1
echo 1-1: ${1}
echo 1-2: ${2}
while [ ${COUNT} -le ${##} ]; do
typeset var PARAM=$(eval "echo \$${COUNT}")
FUNC="${FUNC} \"${PARAM}\""
((COUNT=COUNT+1))
done
eval "${FUNC}"
}
# test1 "" hello
1-1:
1-2: hello
2-1:
2-2: hello
This works very nicely, thank you. Now to my 'problem'.
Is it actually possible to encapsulate the above code in a function of its own? It seems a catch 22 to me, in that you have to run that code to pass the blank parameters. I have to repeat this code snippet many times in my script because I can't find another way. Is there one?
Any help or guidance will be gratefully received.

Here is how I would write your functions:
show_params() {
typeset funcname=$1
typeset -i n=0
shift
for arg; do
((n++))
printf "%s:%d >%s<\n" "$funcname" $n "$arg"
done
}
test1() { show_params "${.sh.fun}" "$#"; test2 "$#"; }
test2() { show_params "${.sh.fun}" "$#"; }
test1 "" 'a string "with double quotes" in it'
test1:1 ><
test1:2 >a string "with double quotes" in it<
test2:1 ><
test2:2 >a string "with double quotes" in it<
Using your definition of test1, which builds up a string containing a command, adding double quotes around all the paramers, and then eval-ing the string, I get this result
$ test1 "" 'a string "with double quotes" in it'
1-1:
1-2: a string "with double quotes" in it
test2:1 ><
test2:2 >a string with<
test2:3 >double<
test2:4 >quotes in it<
That's because you're doing this:
eval "test2 \"\" \"a string \"with double quotes\" in it\""
# ......... A A A B B A
# A = injected quotes
# B = pre-existing quotes contained in the parameter

Related

bjam - cannot assign a literal to a variable?

Well, this must be the most stupid and idiotic behavior I've seen from a programming language.
https://www.bfgroup.xyz/b2/manual/release/index.html says:
Syntactically, a Boost.Jam program consists of two kinds of
elements—keywords (which have a special meaning to Boost.Jam) and
literals. Consider this code:
a = b ;
which assigns the value b to the variable a. Here, = and ; are
keywords, while a and b are literals.
⚠ All syntax elements, even
keywords, must be separated by spaces. For example, omitting the space
character before ; will lead to a syntax error.
If you want to use a literal value that is the same as some keyword,
the value can be quoted:
a = "=" ;
OK, so far so good. So I have this in my Jamroot:
import path : basename ;
actions make_mytest_install
{
echo "make_mytest_install: MY_ROOT_PATH $(MY_ROOT_PATH) PWD $(PWD:E=not_set)" ;
epath = "$(MY_ROOT_PATH)/projects/mytest/bin/gcc-9/release/qt5client" ;
ename = basename ( $(epath) ) ;
echo "epath $(epath) ename $(ename)" ;
}
explicit install-gettext ;
make install-mytest : : #make_mytest_install ;
... and I try this:
bjam install-mytest
...updating 1 target...
Jamfile</home/USER/src/myproject>.make_mytest_install bin/install-mytest
make_mytest_install: MY_ROOT_PATH /home/USER/src/myproject PWD not_set
[ SHELL pstree -s -p 2720269 && echo PID 2720269 PWD /home/USER/src/myproject ]
/bin/sh: 13: epath: not found
/bin/sh: 14: Syntax error: "(" unexpected
.....
...failed Jamfile</home/USER/src/myproject>.make_mytest_install bin/install-mytest...
...failed updating 1 target...
Now - how come that the SIMPLEST assignment to a string, EXACTLY AS in the manual:
epath = "$(MY_ROOT_PATH)/projects/mytest/bin/gcc-9/release/qt5client" ;
... fails, and this variable cannot be found anymore?
What is the logic in this? How the hell is this supposed to work? I would get it if MY_ROOT_PATH was undefined - but the echo before it, shows that it is not? What is this lunacy?
So I cannot believe I'm asking something this trivial, but:
How do you assign a string to a variable in bjam language?
Well, the error gives somewhat of a hint: /bin/sh: -> so apparently inside actions, it is sh that runs - then again, if it was really sh I could have assigned variables, but I can't. So best I could do, was to remove the assignments OUT of actions:
import path : basename ;
epath = "$(MY_ROOT_PATH)/projects/mytest/bin/gcc-9/release/qt5client" ;
# ename = basename ( $(epath) ) ; # nope, causes target install-mytest to not be found :(
# calling a shell for basename works - but adds a damn NEWLINE at end!?!?!?!
ename = [ SHELL "basename $(epath)" ] ;
actions make_mytest_install
{
echo "make_mytest_install: MY_ROOT_PATH $(MY_ROOT_PATH) PWD $(PWD:E=not_set)" ;
echo "epath $(epath) ename $(ename)" ;
}
explicit install-mytest ;
make install-mytest : : #make_mytest_install ;
So, assignment kind of passes, but you still can't get the basename ?!
I still don't understand, who thought this kind of variable management is a good idea ... I don't even understand, how people managed to build stuff with this system

How to initialize array from array in zsh?

My script test.zsh:
args=$#
argss=($#)
echo ${#:2}
echo ${args:2}
echo ${argss:2}
The output:
$ ./test.zsh foo bar foobar
bar foobar
o bar foobar
o
It looks like args is being initialized as the string of $# instead of as an array. How do I initialize args as an array? ($#) does not seem to work either
You need to put parentheses around $# to make args an array:
args=($#)
In other shells, you should also put quotes around it (args=("$#")) to avoid word splitting, but this is disabled by default in zsh (see the option SH_WORD_SPLIT).
Note that ${#:2} will give you $1 $2 $3 ..., while ${args:2} will give $2 $3 ..., because zsh prepends $0 to $# when you use that form of parameter subscripting for compatibility with other shells.
The preferred zsh way to subscript arrays is ${arr[start,end]}, where end is inclusive and may be negative.
${args[1,-1]} and ${args[#]} will expand to the same thing.

How to take string format from command line?

https://stedolan.github.io/jq/manual/#Stringinterpolation-%5C(foo)
I want to pass string format from the command line of jq, instead of embedding the format in string interpolation.
Let's say the format string is "my string %s". How to modify the following jq command to take the format string in its argument so that the output will be "my string x"?
jq --arg format "my string %s" -r -e . <<< '"x"'
Put your (dynamic) jq expression inside \(…), which in turn is part of a (static) string expression "…". If all you want is passing on the input, use the identity function ., and your example should read
jq -r -e '"my string \(.)"' <<< '"x"'
my string x
Demo
Having "my string %s" as a parameter string, you cannot use it for string interpolation, as string interpolation is a language construct, and jq does not provide an eval (or similar) function to evaluate a variable's content as code.
What you can do instead is to (naively) replace %s with something else using sub or gsub:
jq -r -e -n --arg f "my string %s" '$f | sub("%s"; input)' <<< '"x"'
my string x
Demo

zsh completion complete literal quotes

I am writing my own completions for a program.
I would like to be able to complete quoted words, maintaining the double or single quotes in the completion.
#compdef foo
_foo {
local strings
strings=(\
foo\
bar\
'spam eggs')
_arguments \
{-s,--string}'[Select a string]:STR:(\""${strings[#]}"\")\
&& return 0
}
_foo
what I'd expect:
foo -s <TAB>
"foo" "bar" "spam eggs"
what it get:
\"foo\" \"bar\" \"spam\ eggs\"
I ended up trying different combinations of nested quotes and escapes almost brainlessly but with no luck, as I was not able to find the relevant docs (really, zsh docs are "dense")
Thank you!

Match function in unix to find if string ends with particular input value?

I need a regular expression that I can use in match() function to see if value given at command line argument exists at the end of a given string.
I am using awk then trying use match function to get above result:
while read line; do
cat $line | awk -v value="$2.$" '{ if ( match("$1,value) != 0 ) print match("arvind","ind.$") " " "arvind" }'
done < xreffilelist.txt

Resources