Batch use "=" as a string when passing argument - string

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.

Related

^M still at the end of my string even after chop/chomp

I am wanting to pass a string variable in a ssh command. You can see in the code below I ssh to a server then cd to a directory that I pass a variable to. (cd $orig)
The variable is pulled from a file that I read in and put into an array.
I think that is where my error is because there might be unwanted hidden characters after I used the split command to read in from the file.
Here is the error I get:
ksh: /OnSight/jetplan/scripts/release/jscripts^M: not found
Can't open perl script "AddAlias.pl": No such file or directory
/OnSight/users/onsadm
SSHing to densbp53
/OnSight//scripts/release/jscripts
It can't find my script because the CD to the folder fails.
Sometimes the error says that 'end of file' can't be found. Like I'm doing a CD command with a EOF hidden symbol.
And here is the code:
for(my $j=0; $j < $#servName+1; $j++)
{
print "\nSSHing to $servName[$j]\n\n";
my $orig = $scriptfileLoc[$j];
#my $chopped = chop($orig);
chop($orig);
chomp($orig);
print ("\n$orig\n");
$sshstart = `ssh $servName[$j] "cd $orig; pwd; perl AddAlias.pl $aliasName $aliasCommand $addperl $servProfileLoc[$j]"`;
print $sshstart;
}
It outputs the $orig variable and it looks fine after the chop and chomp. (Which I've done both by themselves and still got the same error) So I pass it in my SSH command and it doesnt work.
I have a server file that holds all the server information, and yes it looks repetative I know.
densbp40:/export/home/.profile:/OnSight/scripts/release/jscripts
densbp41:/export/home/.profile:/OnSight/scripts/release/jscripts
densbp42:/export/home/.profile:/OnSight/scripts/release/jscripts
densbp43:/export/home/.profile:/OnSight/scripts/release/jscripts
densbp50:/export/home/.profile:/OnSight/scripts/release/jscripts
densbp51:/export/home/.profile:/OnSight/scripts/release/jscripts
densbp52:/export/home/.profile:/OnSight/scripts/release/jscripts
densbp53:/export/home/.profile:/OnSight/scripts/release/jscripts
densbp60:/export/home/.profile:/OnSight/scripts/release/jscripts
densbp61:/export/home/.profile:/OnSight/scripts/release/jscripts
densbp62:/export/home/.profile:/OnSight/scripts/release/jscripts
tulsbp40:/OnSight/users/.profile:/OnSight/scripts/release/jscripts
tulsbp41:/OnSight/users/.profile:/OnSight/scripts/release/jscripts
tulsbp42:/OnSight/users/.profile:/OnSight/scripts/release/jscripts
tulsbp43:/OnSight/users/.profile:/OnSight/scripts/release/jscripts
tulsbp50:/OnSight/users/.profile:/OnSight/scripts/release/jscripts
tulsbp51:/OnSight/users/.profile:/OnSight/scripts/release/jscripts
tulsbp52:/OnSight/users/.profile:/OnSight/scripts/release/jscripts
tulsbp53:/OnSight/users/.profile:/OnSight/scripts/release/jscripts
densbcp1:/OnSight/users/.profile:/OnSight/scripts/release/jscripts
densbcp2:/OnSight/users/.profile:/OnSight/scripts/release/jscripts
densmsv1:/OnSight/.profile:/OnSight/scripts/jscripts
denamdp1:/OnSight/users/.profile:/OnSight/scripts/release/jscripts
denamap1:/OnSight/users/profile:/OnSight/scripts/release/jscripts
denamap2:/OnSight/users/.profile:/OnSight/scripts/release/jscripts
denfpev1:/OnSight/users/.profile:/OnSight/scripts/release/jscripts
This script asks the user to choose to send a file to ALL servers or just one.
To remove CR (^M) from the end of lines, use the following regex:
$orig =~ s/\r$//gm;
Anchoring at the line end guarantees that any other carriage return characters are not removed from your input. (You probably don't them there either, but to normalize line endings, it's better to not touch other characters).
g enables global matches (not only the first) and m enables multiline mode, so that $ matches the end of each line in a multiline string, not only the end of the string.
"^M" is carriage return a.k.a "\r". Use regex to remove it:
$orig =~ s/\r//g;

How do I assign a File into a variable to work with that variable? [duplicate]

I have this script called test.sh:
#!/bin/bash
STR = "Hello World"
echo $STR
when I run sh test.sh I get this:
test.sh: line 2: STR: command not found
What am I doing wrong? I look at extremely basic/beginners bash scripting tutorials online and this is how they say to declare variables... So I'm not sure what I'm doing wrong.
I'm on Ubuntu Server 9.10. And yes, bash is located at /bin/bash.
You cannot have spaces around the = sign.
When you write:
STR = "foo"
bash tries to run a command named STR with 2 arguments (the strings = and foo)
When you write:
STR =foo
bash tries to run a command named STR with 1 argument (the string =foo)
When you write:
STR= foo
bash tries to run the command foo with STR set to the empty string in its environment.
I'm not sure if this helps to clarify or if it is mere obfuscation, but note that:
the first command is exactly equivalent to: STR "=" "foo",
the second is the same as STR "=foo",
and the last is equivalent to STR="" foo.
The relevant section of the sh language spec, section 2.9.1 states:
A "simple command" is a sequence of optional variable assignments and redirections, in any sequence, optionally followed by words and redirections, terminated by a control operator.
In that context, a word is the command that bash is going to run. Any string containing = (in any position other than at the beginning of the string) which is not a redirection and in which the portion of the string before the = is a valid variable name is a variable assignment, while any string that is not a redirection or a variable assignment is a command. In STR = "foo", STR is not a variable assignment.
Drop the spaces around the = sign:
#!/bin/bash
STR="Hello World"
echo $STR
In the interactive mode everything looks fine:
$ str="Hello World"
$ echo $str
Hello World
Obviously(!) as Johannes said, no space around =. In case there is any space around = then in the interactive mode it gives errors as
No command 'str' found
I know this has been answered with a very high-quality answer. But, in short, you cant have spaces.
#!/bin/bash
STR = "Hello World"
echo $STR
Didn't work because of the spaces around the equal sign. If you were to run...
#!/bin/bash
STR="Hello World"
echo $STR
It would work
When you define any variable then you do not have to put in any extra spaces.
E.g.
name = "Stack Overflow"
// it is not valid, you will get an error saying- "Command not found"
So remove spaces:
name="Stack Overflow"
and it will work fine.

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

escape a whole array of arguments for use in sh-like shells with a standard tool

I'm looking for a standard tool capable of taking all of its arguments and turning it into a single string suitable for use as multiple arguments in an automatically generated bash/sh/zsh script. Such a command is extremely useful in various disciplines of script-fu. An example of its usage:
% shsafe 'A big \nasty string '\'' $HOME $PATH' 'another string \\'
'A big \nasty string '\'' $HOME $PATH' 'another string \\'
Using it in another script:
% sshc host rm 'file/with spaces and $special chars'
where sshc contains
#!/bin/bash
# usage: sshc host command [arg ...]
# Escapes its arguments so that the command may contain special
# characters. Assumes the remote shell is sh-like.
host=$1
shift
exec ssh "$host" "$(shsafe "$#")"
Another example:
#!/bin/bash
# Run multiple commands in a single sudo session. The arguments of
# this script are passed as arguments to the first command. Useful if
# you don't want to have to type the password for both commands and
# the first one takes a while to run.
sudo bash -c "pacman -Syu $(shsafe "$#") && find /etc -name '*.pacnew'"
I couldn't find a suitable solution to this problem in the pre-existing commands, so I made up my own, called shsafe. It uses the fact that single quotes, '', turn off absolutely all shell expansion, except for ' itself.
shsafe:
#!/usr/bin/env python
from sys import *
n = len(argv)
if n == 1:
exit(0)
i = 1
while True:
stdout.write("'" + argv[i].replace("'", "'\\''") + "'")
i += 1
if i == n:
break
stdout.write(' ')
stdout.write('\n')
Is there any standard tool capable of doing this to its arguments?
Note that the printf command with a format string consisting of just the %q formatter is not good enough for this, because it won't keep multiple arguments separated:
% printf %q arg1 arg2
arg1arg2
I did eventually figure out a decent way of doing this:
% printf "$'%q' " 'crazy string \ $HOME' 'another\ string'
$'crazy\ string\ \\\ \$HOME' $'another\\\ string'
It's a little error prone what with the quotes everywhere, so it's not ideal, IMO, but it's a solid solution that should work anywhere. If it's being used a lot, you could always turn it into a shell function:
shsafe () {
printf "$'%q' " "$#"
}

KornShell Printf - Padding a string

I'm attempting to write a KornShell (ksh) function that uses printf to pad a string to a certain width.
Examples:
Call
padSpaces Hello 10
Output
'Hello '
I currently have:
padSpaces(){
WIDTH=$2
FORMAT="%-${WIDTH}.${WIDTH}s"
printf $FORMAT $1
}
Edit: This seems to be working, in and of itself, but when I assign this in the script it seems to lose all but the first space.
TEXT=`padSpaces "TEST" 10`
TEXT="${TEXT}A"
echo ${TEXT}
Output:
TEST A
I'm also open to suggestions that don't use printf. What I'm really trying to get at is a way to make a fixed width file from ksh.
Your function works fine for me. Your assignment won't work with spaces around the equal sign. It should be:
SOME_STRING=$(padSpaces TEST 10)
I took the liberty of replacing the backticks, too.
You don't show how you are using the variable or how you obtain the output you showed. However, your problem may be that you need to quote your variables. Here's a demonstration:
$ SOME_STRING=$(padSpaces TEST 10)
$ sq=\'
$ echo $sq$SOME_STRING$sq
'TEST '
$ echo "$sq$SOME_STRING$sq"
'TEST '
Are you aware that you define a function called padSpaces, yet call one named padString? Anyway, try this:
padString() {
WIDTH=$2
FORMAT="%-${WIDTH}s"
printf $FORMAT $1
}
Or, the more compact:
padString() {
printf "%-${2}s" $1
}
The minus sign tells printf to left align (instead of the default right alignment). As the manpage states about the command printf format [ arg ... ],
The arguments arg are printed on standard output in accordance with the
ANSI-C formatting rules associated with the format string format.
(I just installed ksh to test this code; it works on my machineTM.)

Resources