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
Related
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 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'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!
I've got a problem with a bash script in which I'd like to execute SQL.
As an example if I simply write :
sqlplus -s << EOF
${USER}/${PASSWD}#DataBase
show user;
exit;
it works.
But as soon as I put it into a loop it doesn't work anymore.
For example :
while (condition)
do
echo $ANSWER
read -p '[y/n]' ANSWER
echo $ANSWER
if [ $ANSWER = 'y' ]
then
sqlplus -s << EOF
${USER}/${PASSWD}#DataBase
show user;
exit;
EOF
break
elif [ $ANSWER = 'n' ]
then
break
fi
done
echo $ANSWER
And the results I've got is : line 26: syntax error : unexpected end of file
(knowing that the line "echo $ANSWER" is the line 25...)
If anyone has an idea about why it doesn't want to work I will be really thankful for the help !
Your problem is that the shell expects the delimiter for the here document at the beginning of the line.
Your EOF is in the middle of the line, and therefore it isn't recognized as a delimiter anymore.
This works as expected:
while (true)
do
echo $ANSWER
read -p '[y/n]' ANSWER
echo $ANSWER
if [ $ANSWER = 'y' ]
then
sqlplus -s << EOF
${USER}/${PASSWD}#DataBase
show user;
exit;
EOF
break
elif [ $ANSWER = 'n' ]
then
break
fi
done
echo $ANSWER
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"