Check and modify format of variable in expect script - linux

I am trying to verify that the format of a variable is a number and is at least 10 digits long with leading zeros, inside of an expect script.
In a bash script it would look something like this:
[[ "$var" != +([0-9]) ]] && echo "bad input" && exit
while [[ $(echo -n ${var} | wc -c) -lt 10 ]] ; do var="0${var}" ; done
For the following input:
16
I am trying to achieve the following output:
0000000016

The simplest way to check whether a variable has just digits is to use a regular expression. Expect's regular expressions are entirely up to the task:
if {![regexp {^\d+$} $var]} {
puts "bad input"
exit
}
Padding with zeroes is best done by formatting the value; if you know C's printf(), you'll recognize the format:
set var [format "%010d" $var]

Expect is actually just an extension of TCL, so you can use any facility that TCL provides. TCL is an unusual language, but it's not hard to do what you want.
# Set a test string.
set testvar 1234567890
# Store the match (if any) in matchvar.
regexp {\d{10,}} $testvar matchvar
puts $matchvar
# Test that matchvar holds an integer.
string is integer $matchvar
The string is command is relatively new, so you might have to rely on the return value of regexp if your TCL interpreter doesn't support it.

Related

Bash for loop on variable numbers

I have a situation where I have large number of numbered variables. I want to evaluate each variable and set variable to a specific string if the condition is matched.
#!/bin/bash
var1=""
var2="1233123213"
var3="22332323222324242"
var4=""
var5=""
for i in 1 2 3 4 5
do
if [ -z "$var{$}i" ]
then
var{$}i="None"
fi
echo "var{$}i \r"
done
but the problem is when I run the script I get following.
{1} \r
{2} \r
{3} \r
{4} \r
{5} \r
How I can fix this.
Use indirect variable expansion in bash with syntax {!var}.
From the man bash page,
If the first character of parameter is an exclamation point (!), a level of variable indirection is introduced. Bash uses the value of the variable formed from the rest of parameter as the name of the variable; this variable is then expanded and that value is used in the rest of the substitution, rather than the value of parameter itself. This is known as indirect expansion. The exclamation point must immediately follow the left brace in order to introduce indirection.
Modify your code to something like below,
for i in 1 2 3 4 5
do
var="var$i"
[ -z "${!var}" ] && declare "var$i"="none"
done
printf "var1=%s\n" "$var1"
printf "var2=%s\n" "$var2"
printf "var3=%s\n" "$var3"
printf "var4=%s\n" "$var4"
printf "var5=%s\n" "$var5"
The syntax "${!var}" in this case evaluates the value of the variable within the string var which is var1, var2, var3... and the declare syntax sets the variable value at run-time, only for those variables that are empty.
Now on printing those variables produces,
var1=none
var2=1233123213
var3=22332323222324242
var4=none
var5=none
Indirect assignment will work here, but in this specific case arrays seem like a good fit :
#!/bin/bash
declare -a var=()
var+=("")
var+=(1233123213)
var+=(22332323222324242)
var+=("")
var+=("")
for i in "${!var[#]}"
do
[[ "${var[$i]}" ]] || var[$i]="None"
echo "Index: $i - Value: ${var[$i]}"
done
Consider using an array instead of numbered variables:
#!/bin/bash
var[1]=""
var[2]="1233123213"
var[3]="22332323222324242"
var[4]=""
var[5]=""
for i in 1 2 3 4 5
do
if [ -z "${var[i]}" ]
then
var[i]="None"
fi
echo "${var[i]} \r"
done

How do you compare the value of an array to a variable in bash script?

I'm practicing bash and honestly, it is pretty fun. However, I'm trying to write a program that compares an array's value to a variable and if they are the same then it should print the array's value with an asterisk to the left of it.
#!/bin/bash
color[0]=red
color[1]=blue
color[2]=black
color[3]=brown
color[4]=yellow
favorite="black"
for i in {0..4};do echo ${color[$i]};
if {"$favorite"=$color[i]}; then
echo"* $color[i]"
done
output should be *black
There's few incorrect statements in your code that prevent it from doing what you ask it to. The comparison in bash is done withing square brackets, leaving space around them. You correctly use the = for string comparison, but should enclose in " the string variable. Also, while you correctly address the element array in the echo statement, you don't do so inside the comparison, where it should read ${color[$i]} as well. Same error in the asterisk print. So, here a reworked code with the fixes, but read more below.
#!/bin/bash
color[0]=red
color[1]=blue
color[2]=black
color[3]=brown
color[4]=yellow
favorite=black
for i in {0..4};do
echo ${color[$i]};
if [ "$favorite" = "${color[$i]}" ]; then
echo "* ${color[$i]}"
fi
done
While that code works now, few things that probably I like and would suggest (open to more expert input of course by the SO community): always enclose strings in ", as it makes evident it is a string variable; when looping an array, no need to use index variables; enclose variables always within ${}.
So my version of the same code would be:
#!/bin/bash
color=("red" "blue" "black" "brown" "yellow")
favorite="black"
for item in ${color[#]}; do
echo ${item}
if [ "${item}" = "${favorite}" ]; then
echo "* $item"
fi
done
And a pointer to the great Advanced Bash-Scripting Guide here: http://tldp.org/LDP/abs/html/

Compare values in Linux

I'm using .conf which contain keys and values.
Some keys contains numbers like
deployment.conf
EAR_COUNT=2
EAR_1=xxx.ear
EAR_2=yyy.ear
When I try to retrieve that value using particular key and compare with integer value i.e. natural number.
But Whatever I retrieved values from .conf ,it is should be String datatype.
How should I compare both value in Linux Bash script.
Simply : How should I compare two values in Linux.?
Ex :
. ./deployment.conf
count=$EAR_COUNT;
echo "count : $count";
if [ $count -gt 0 ]; then
echo "Test"
fi
I'm getting following error :
count : 2
: integer expression expected30: [: 2
They're all strings in bash, notwithstanding your ability to do typeset-type things to flag them differently.
If you want to do numeric comparisons, just use -eq (or its brethren like -gt, -le) rather than ==, != and so on:
if [[ $num -eq 42 ]] ; then
echo Found the answer
fi
The full range of comparison operators can be found in the bash manpage, under CONDITIONAL EXPRESSIONS.
If you have something that you think should be a number and it's not working, I'll warrant it's not a number. Do something like:
echo "[$count]"
to make sure it doesn't have a newline at the end or, better yet, get a hex dump of it in case it holds strange characters, like Windows line endings:
echo -n $count | od -xcb
The fact that you're seeing:
: integer expression expected30: [: 2
with the : back at the start of the line, rather than the more usual:
-bash: [: XX: integer expression expected
tends to indicate the presence of a carriage return in there, which might be from deployment.conf having those Windows line endings (\r\n rather than the UNIXy \n).
The hex dump should make that obvious, at which point you need to go and clean up your configuration file.
Ref : http://linux.die.net/man/1/bash
-eq, -ne, -lt, -le, -gt, or -ge
These are arithmetic binary operators in bash scripting.
I have checked your code,
deployment.conf
# CONF FILE
EAR_COUNT=5
testArithmetic.sh
#!/bin/bash
. ./deployment.conf
count=$EAR_COUNT;
echo "count : $count";
if [ $count -gt 0 ]; then
echo "Test"
fi
running the above script evaluates to numeric comparison for fine. Share us your conf file contents, if you are facing any issues. If you are including the conf file in your script file, note the conf file must have valid BASH assignments, which means, there should be no space before and after '=' sign.
Also, you have mentioned WAR_COUNT=3 in conf part and used 'count=$EAR_COUNT;' in script part. Please check this too.
Most likely you have some non-integer character like \r in your EAR_COUNT variable. Strip all non-digits while assigning to count like this:
count=${EAR_COUNT//[^[:digit:]]/}
echo "count : $count";
if [[ $count -gt 0 ]]; then
echo "Test"
fi

Shell Programming: Access Element of List

It is my understanding that when writing a Unix shell program you can iterate through a string like a list with a for loop. Does this mean you can access elements of the string by their index as well?
For example:
foo="fruit vegetable bread"
How could I access the first word of this sentence? I've tried using brackets like the C-based languages to no avail, and solutions I've read online require regular expressions, which I would like to avoid for now.
Pass $foo as argument to a function. Than you can use $1, $2 and so on to access the corresponding word in the function.
function try {
echo $1
}
a="one two three"
try $a
EDIT: another better version is:
a="one two three"
b=( $a )
echo ${b[0]}
EDIT(2): have a look at this thread.
Using arrays is the best solution.
Here's a tricky way using indirect variables
get() { local idx=${!#}; echo "${!idx}"; }
foo="one two three"
get $foo 1 # one
get $foo 2 # two
get $foo 3 # three
Notes:
$# is the number of parameters given to the function (4 in all these cases)
${!#} is the value of the last parameter
${!idx} is the value of the idx'th parameter
You must not quote $foo so the shell can split the string into words.
With a bit of error checking:
get() {
local idx=${!#}
if (( $idx < 1 || $idx >= $# )); then
echo "index out of bounds" >&2
return 1
fi
echo "${!idx}"
}
Please don't actually use this function. Use an array.

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