I'm trying to change the value of a Boolean variable using expression in bash script (Debian Jessie) but it's not working as intended!
Here is my code
vld=true
while ! [ $vld ]
do
echo "Enter a number: [1-30]:"
read myinput
$vld=[ $myinput -ge 1 ] && [ $myinput -le 30 ]
done
echo "Your number is $myinput
When I this script it says:
8: ./test.sh true=[: not found
Then it keeps on the loop as the variable is not receiving the result of the expression but is used itself!
Related
I want to create a while loop that request the user input for yes or no, if the user enter anything else it will loop until the user enters either yes or no
echo "Do you wish to save these settings?"
read response
while [ "$response" != "yes" ] | [ "$response != "no" ]
do
echo "Please enter yes or no only"
echo "Do you wish to save these settings?"
read response
done
when i tried entering yes it still continues to loop but when i enter no it exits the loop
In shell, the | (or pipe) operator is used to filter the output of the command on the left using the command on the right.
For example, the following line of shell:
seq 1 3 | tac
...will result in the lines produced by the command on the left...
1
2
3
...to be filtered by the command on the left (which will emit the lines in reverse order). The output will be:
3
2
1
You're after an operator that performs a boolean operation on the exit statuses of two commands. Since you're looking to continue the loop as long as the response is neither yes or no, the conjunction operator (&&) is what you're after:
echo "Do you wish to save these settings?"
read response
while [ "$response" != "yes" ] && [ "$response" != "no" ]
do
echo "Please enter yes or no only"
echo "Do you wish to save these settings?"
read response
done
If the bash shell will always be available wherever you're running your script, this could be improved further by using [[ ... ]] instead of [ ... ]. Besides a potential performance benefit, another advantage of using [[ is that the requirements on strict quoting are relaxed:
echo "Do you wish to save these settings?"
read response
while [[ $response != yes ]] && [[ $response != no ]]
do
echo "Please enter yes or no only"
echo "Do you wish to save these settings?"
read response
done
A further improvement comes from the knowledge that [[ supports && to conjoin two boolean expressions:
echo "Do you wish to save these settings?"
read response
while [[ $response != yes && $response != no ]]
do
echo "Please enter yes or no only"
echo "Do you wish to save these settings?"
read response
done
Just while true the whole thing until satisfied:
while true
do
echo "Do you wish to save these settings?"
read response
if [[ "$response" = "yes" ]] || [[ "$response" = "no" ]]
then
break
fi
echo "Please enter yes or no only"
done
Let's say I have a conditional Tcl expression that is a boolean combination of steps.
Will the expression always be evaluated left to right (excluding parentheses)?
If the expression becomes true will the rest of the evaluation stop?
I have this piece of code that parses a file and conditionally replaces stuff in the lines.
set fp [ open "file" ]
set data [ read $fp ]
close $fp
foreach line [ split $data \n ] {
if { $enable_patch && [ regsub {<some_pattern>} $line {<some_other_pattern>} line ]} {
puts $outfp $line
<do_some_more_stuff>
}
}
So my issue here is that unless enable_patch is true, I don't want the line to be modified. Now my test shows that the code is deterministic in Tcl 8.5 on Linux. But I am wondering if this would break under other conditions/ versions/ OSes.
Yes, the || and && operators are "short-circuiting" operators in TCL. That means you can rely on them being evaluated left-to-right, and that evaluation will stop as soon as the value of the expression is known.
I'm writing script for git hook and have trouble with if statement inside while.
File:
#!/bin/sh
while read oldrev newref ref
do
branch=$(git rev-parse --symbolic --abbrev-ref $ref)
if [ "a" == "a" ]
then
echo "Condition work"
fi
echo "$branch"
done
Error:
hooks/post-receive: 6: [: a: unexpected operator
I'll try with variables, double quotes but if doesn't work. What kind of error is here?
Thanks
if [ "a" == "a" ] should be if [ "a" = "a" ].
bash accepts == instead of =, but your /bin/sh probably isn't bash.
So either change the == to =, or your shebang to #!/bin/bash
I would like to call different other scripts, depending on whether a paramter is given or not:
"paramtest": "if [ -z $1 ]; then echo Foo $1; else echo Bar; fi",
npm run paramtest
should give "Bar".
npm run paramtest -- whatever
should give "Foo whatever".
However in practice I only get: (The parameter is added to the whole line, not 'passed in')
> if [ -z $1 ]; then echo Foo; else echo Bar; fi "whatever
sh: 1: Syntax error: word unexpected
What can I do better?
Essentially I am after running full test suite / only individual test with the same command...
"test" : "if [ -z $1 ]; then mocha ./test/**/*.test.js; else mocha $1
Wrapping it in a shell function should do the trick:
"test": "f() { if [ $# -eq 0 ]; then mocha './test/**/*.test.js'; else mocha -- \"$#\"; fi; }; f"
Note that I changed the if condition and the else branch slightly so you can specify multiple file arguments if necessary.
A more succinct method:
"test": "f() { mocha -- \"${#:-./test/**/*.test.js}\"; }; f"
Using a shell function this way might look familiar, as the same technique is often used for git aliases.
Detailed Explanation
Let's use this script for demonstration:
"scripts": {
"myscript": "if [ \"$1\" = one ]; then printf %s\\\\n \"$#\"; else echo false; fi"
}
Here if the first argument is "one", we print all the arguments, and otherwise we print "false". We are of course assuming that npm run-script is using an sh-like shell, and not, e.g., Windows' cmd.exe.
I can't see anything in the npm documentation specifically detailing how arguments are passed to the script, so let's take a look at the source code (npm v6.14.7 at the time of writing). It seems that the script is joined with its arguments here and is then executed here. Essentially, npm run myscript -- one two three becomes
sh -c 'if [ "$1" = one ]; then printf %s\\n "$#"; else echo false; fi "one" "two" "three"'
Our arguments one two three are simply quote-escaped and concatenated to the script command. In terms of the shell grammar, this means that they are ending up as arguments to fi. sh of course rejects this because fi is just a builtin to end if and takes no arguments.
Our goal is something more like
sh -c 'if [ "$1" = one ]; then printf %s\\n "$#"; else echo false; fi' sh "one" "two" "three"
Here one, two, and three are arguments to sh itself and thus become the argument variables $1, $2, and $3 in the given script. npm doesn't let us do this directly, but we can accomplish the same thing by wrapping our script in a shell function:
"scripts": {
"myscript": "f() { if [ \"$1\" = one ]; then printf %s\\\\n \"$#\"; else echo false; fi; }; f"
}
The script here ends with an invocation of the function, so npm will end up concatenating the arguments to this invocation, ultimately calling the function as f "one" "two" "three":
sh -c 'f() { if [ "$1" = one ]; then printf %s\\n "$#"; else echo false; fi; }; f "one" "two" "three"'
I read this stackoverflow question...
Bash: check user input is correct
which does most of what I want however rather then checking it's just an integer I need to check it's an integer in a variable range....
The script looks for files in a directory and then assigns a number to them...
File 1
File 2
File 3
etc....
The user chooses the the number and the script then executes commands against that file.....the variable $FILELIST is the total number of files.
Taking the example from the previous stackoverflow I tried.....
FILENUM=""
while [[ ! ($FILENUM =~ ^[0-$FILELIST]+$) ]]; do
echo " "
echo "Please enter the file number: "
read -p "1 - $FILELIST" FILENUM < /dev/tty
done
echo "$FILENUM"
However this is throwing a syntax error: unexpected "(" (expecting "do") in the while line and I'm not sure why, I suspect $FILELIST has to be bracketed somehow but an explanation as to why the above works would help me understand the problem.
Thanks
bash-specific answers:
You don't need to reinvent the wheel: use the select builtin:
cd /path/to/directory
PS3="Select a file: "
select file in *; do
if [[ $file ]]; then break; fi
done
echo "You selected '$file'"
echo "You selected file number $REPLY"
To check a number is within a certain range, I'd write:
if (( 0 <= $number && $number <= $max )); then echo "in range"; fi
Since you're using ash you might use this as a reference: http://manpages.debian.net/cgi-bin/man.cgi?query=dash
while true; do
FILENUM=""
echo
echo "Please enter the file number: "
read -p "1 - $FILELIST" FILENUM < /dev/tty
if expr "$FILENUM" : '[0-9]\+$' &&
[ $FILENUM -gt 0 ] &&
[ $FILENUM -le $FILELIST ]
then
break
fi
done
echo "$FILENUM"