Positional Parameters in C-shell - linux

I am unable to print positional parameters using this shell command: echo $1.
I am using it as following two commands:
% set hi how are you
% echo $1
Nothing get out of the command, but hi should be print.

In csh, you need to assign to the argv array:
> set argv=(hi how are you)
> echo $1
hi
Explanation:
argv is an array variable which contains the command line argument list (the 0th argument is name as the shell was invoked and the other start from 1th index). Variables $0 - $n also contain values of the arguments . So $argv[1] is the same as $1. To assign to an array variable, you can use either set arr=(value1 value2) or set arr[1] = value1.
set value1 value2 would work in bash, but csh is meant to be similar to the C language, therefore the argv array is used (read a little about C program command line arguments if you don't know why).
But in csh, this: set first second means assigning an empty (null) value to the variables first and second.

Related

Batch use "=" as a string when passing argument

funtion.bat echo variables
set "Var1=%1"
set "Var2=%2"
set "Var3=%3"
echo %Var1% %Var2% %Var3%
I use a batch that calls this function by passing 3 arguments
call function.bat blabla= argument2 TEST.txt
As you see my first argument has an equal sign in it. But I want to use it as a string and not as an operator.
When I run the batch this is the result that I get:
blabla
argument2
TEST.txt
This is the result that I want:
blabla=
argument2
TEST.txt
Does anyone have an idea of how to get "blabla="?
From cmd /? in cmd:
The special characters that require quotes are:
<space>
&()[]{}^=;!'+,~ `
As you can see, you should quote almost everything that contains = because it is used as a separator. You should run your batch file with the command:
call function.bat "blabla=" "argument2" "TEST.txt"
in cmd and then remove the double quotes for each argument using the following code (the ~ modifier):
set "Var1=%~1"
set "Var2=%~2"
set "Var3=%~3"
echo %Var1% %Var2% %Var3%
and it should work. This way is recommended for best practice. Do it always.

execute external program in lua without userinput as arguments in lua

I want to execute an external program in lua. Usually this can be done with
os.execute("run '"..arg0.."' 'arg1' arg2")
The problem with this approach is if I want to pass user input as string to an external program, user input could be '; evil 'h4ck teh system' ' and the script from above would execute like this:
/bin/bash -c "run ''; evil 'h4ck teh system' '' 'arg1' arg2"
Another problem occurs when I have '$var' as argument and the shell replaces this with its environment variable. In my particular case I have something like [[program 'set title "$My Title$"']] – so nested strings – and program parses "$My Title$" (with escape sequences) differently than '$My Title$' (as it is). Because I want to set the title as it, the best way is to have arguments like this: 'My Title'. But now the command have to be:
os.execute([[run "set title '$My Title$'"]])
But now – as I said – $My will be replaced with an empty string, because the environment does not know any variable named $My and because, I never wanted it to be replaced.
So I am looking for the usual approach with
execv("run", {"set title '"..arg0.."'", arg1, arg2})
local safe_unquoted = "^[-~_/.%w%%+,:#^]*$"
local function q(text, expand) -- quoting under *nix shells
-- "expand"
-- false/nil: $var and `cmd` must NOT be expanded (use single quotes)
-- true: $var and `cmd` must be expanded (use double quotes)
if text == "" then
text = '""'
elseif not text:match(safe_unquoted) then
if expand then
text = '"'..text:gsub('["\\]', '\\%0')..'"'
else
local new_text = {}
for s in (text.."'"):gmatch"(.-)'" do
new_text[#new_text + 1] = s:match(safe_unquoted) or "'"..s.."'"
end
text = table.concat(new_text, "\\'")
end
end
return text
end
function execute_commands(...)
local all_commands = {}
for k, command in ipairs{...} do
for j = 1, #command do
if not command[j]:match"^[-~_%w/%.]+$" then
command[j] = q(command[j], command.expand)
end
end
all_commands[k] = table.concat(command, " ") -- space is arguments delimiter
end
all_commands = table.concat(all_commands, ";") -- semicolon is commands delimiter
return os.execute("/bin/bash -c "..q(all_commands))
end
Usage examples:
-- Usage example #1:
execute_commands(
{"your/program", "arg 1", "$arg2", "arg-3", "~/arg4.txt"},
{expand=true, "echo", "Your program finished with exit code $?"},
{"ls", "-l"}
)
-- The following command will be executed:
-- /bin/bash -c 'your/program '\''arg 1'\'' '\''$arg2'\'' arg-3 ~/arg4.txt;echo "Your program finished with exit code $?";ls -l'
$arg2 will NOT be expanded into value because of single quotes around it, as you required.
Unfortunately, "Your program finished with exit code $?" will NOT be expanded too (unless you explicitly set expand=true).
-- Usage example #2:
execute_commands{"run", "set title '$My Title$'", "arg1", "arg2"}
-- the generated command is not trivial, but it does exactly what you need :-)
-- /bin/bash -c 'run '\''set title '\''\'\'\''$My Title$'\''\'\'' arg1 arg2'

How to iterate over the arguments of type string in the bash script?

An argument is passed to bash script from outside and is read within bash file. Looks like as follows:
#following is the point from where the argument is passed to config.sh
controller.vm.provision :shell, path: 'shell/config.sh', keep_color: true, privileged: false, :args => ip
inside the config.sh reading the argument. The argument "ip" is somewhat like following:
ip = "10.12.153.26" "10.12.153.25" "10.12.153.24"
Now i want to iterate over the above argument inside the bash. so doing as follows:
array=($1) //please note $1="10.12.153.26" "10.12.153.25" "10.12.153.24"
for i in ${array[#]}
do
echo $i //it is iterated only once and output is "10.12.153.26" "10.12.153.25" "10.12.153.24"
done
So the output i am getting only once and is complete argument as it is but i want it to get displayed one by one so, that i can even use the single value separately for some other purpose. So, please suggest how can i have this?
If you want to split the value on spaces, you can do like this:
set -- $1
for i; do
echo $i
done
If the value of $i is "10.12.153.26" "10.12.153.25" "10.12.153.24",
then this will output:
"10.12.153.26"
"10.12.153.25"
"10.12.153.24"
To get rid of the double-quotes, you could use parameter expansion:
set -- $1
for i; do
echo ${i//\"/}
done

Assigning one variable to another in Bash?

I have a doubt. When i declare a value and assign to some variable, I don't know how to reassign the same value to another variable. See the code snippet below.
#/bin/sh
#declare ARG1 to a
a=ARG1
#declaring $a to ARG2
ARG2=$`$a`
echo "ARG 2 = $ARG2"
It should display my output as
ARG 2 = ARG1
...but instead the actual output is:
line 5: ARG1: command not found
ARG 2 = $
To assign the value associated with the variable dest to the variable source, you need simply run dest=$source.
For example, to assign the value associated with the variable arg2 to the variable a:
a=ARG1
arg2=$a
echo "ARG 2 = $arg2"
The use of lower-case variable names for local shell variables is by convention, not necessity -- but this has the advantage of avoiding conflicts with environment variables and builtins, both of which use all-uppercase names by convention.
You may also want to alias rather than copy the variable. For example, if you need mutation. Or if you want to run a function multiple times on different variables. Here's how it works
Example:
C=cat
declare -n VAR=C
VAR+=" says Hi"
echo "$C" # prints "cat says Hi"
Example with arrays/dictionaries:
A=(a a a)
declare -n VAR=A # "-n" stands for "name", e.g. a new name for the same variable
VAR+=(b)
echo "${A[#]}" # prints "a a a b"
That is, VAR becomes effectively the same as the original variable. Instead of copying, you're adding an alias. Here's an example with functions:
function myFunc() {
local -n VAR="$1"
VAR="Hello from $2"
echo "I've set variable '$1' to value '$VAR'"
}
myFunc Inbox Bob # I've set variable 'Inbox' to value 'Hello from Bob'
myFunc Luke Leia # I've set variable 'Luke' to value 'Hello from Leia'
echo "$Luke" # Hello from Leia
Whether you should use these approaches is a question. Generally, immutable code is easier to read and to reason about (in almost any programming language). However, sometimes you really need to get stuff done in a certain way. Hope this answer helps you then.

linux print variable vaule in foreach loop a1,a2,a3

I have a an old csh script (which hopefully I have time to rewrite in perl) which has a series of variables wmr1, wmr2 ... wmr24. What I would like to do is echo the values of each variable using a foreach loop eg
foreach i(`seq 1 24`)
echo ${wmr$i}
end
Can this be done in csh or using a perl one liner (using a symbolic refernce?)? I am not sure how to combine the integer $i with wmr and output the value of $wmr1 $wmr2 etc. echo ${wmr$i} in the loop gives me the error Missing }.
You can try this
foreach i (`seq 1 24`)
eval 'echo $wm'$i
end
The eval statement will evaluate the string given to it.
So replace echo with any other command you may want to use.

Resources