Trouble getting shell script to work with simple conditional statement - shell

This is part of a bigger project but I can't get this part to work and I'm having a brain fart.
#!/bin/bash
echo -n "Do you wish to download/checkout the source code? > "
read text
if ["$text" = "Yes"]
then
do something
else
do something else
fi
It should simply be reading in what the user types and then go through a simple conditional. but I get this error
./check.sh: line 6: [Yes: command not found
I thought I had formatted the shell script correctly but I guess not.

Add spaces after brackets:
if [[ "$text" = "Yes" ]]
When performing operations on strings it's always a good idea to use double square brackets. It will make your code work properly with spaces and new lines.

Related

Removing unneeded information in filename using bash script

I need to remove everything before and after a name in bash script, the following are examples
test_3123_123_testone-2.cpp
abc_3123_12312_a.cpp
johnchase_4123123123_123123123_johnc-1.cpp
I would need them simply change into
testone.cpp
a.cpp
johnc.cpp
But having trouble with regex and trying to get this setup properly, any advice would be great!
the text right before .cpp but ignoring any dashes(-2) if they exist behind it.
Do exactly that. Write it from the end.
"before .cpp" -> so .cpp must be last
"ignoring any dashes" - so there is a dash(-2)
"if they exist behind it" - the dash is optional
"the text" - so match the text.
var=test_3123_123_testone-2.cpp
[[ "$var" =~ ([^_-]*)(-[0-9]+)?.cpp$ ]]
echo ${BASH_REMATCH[1]}.cpp
If your filename is in a variable called file, then: echo ${${file##*_}/-[0-9]*[.]/.}.
Breaking that down, inside out:
${file$$*_} remove everything from start of string to last _
${file/-[0-9]*[.]/.} replace "dash number dot" with just a dot
This is not bullet-proof, but it covers the given cases.
$ for file in test_3123_123_testone-2.cpp abc_3123_12312_a.cpp johnchase_4123123123_123123123_johnc-1.cpp
do
echo ${${file##*_}/-[0-9]*[.]/.}
done
testone.cpp
a.cpp
johnc.cpp

Bash Script for loop with nested if statement

I have a script like this:
#!/bin/bash
x=${1:-20}
for ((i=1;i<=x;i++))
{
if ((i%3==0))
{
echo 'Fizz'
}
echo $i
}
I get an error color on the last brace in VIM and when I try to run the script I get a "syntax error near unexpected token" for that same brace. Without the nested if statement, this will print 1 through 20 on a new line for each number, which is the expected outcome. If the number is divisible by 3, it should print Fizz instead of that number. I'm not as worried about how to implement the replacement, that should be easy to figure out, but what I don't understand is why I cannot use a brace to close the for loop. If I take out the brace, I get an error that says end of file expected. So what is the proper syntax for ending a for loop with a nested if statement? I've looked around online and here on stack but haven't found a similar format to what I am trying to do. I don't like the
for f in *
format as it is not as easy to read for someone coming from a different coding language and I like to keep my code looking very similar across different languages (I use comments too, but just the same, I try to keep things as similar as possible which is why I used (( )) with the for loop.)
If I comment out the if statement and leave everything else intact, the error disappears and it will print
1
Fizz
2
Fizz
etc.
Any insight into this would be greatly appreciated. Thanks!
So here is what I was able to figure out thanks to #Cyrus:
x=${1:-20}
for ((i=1;i<=x;i++))
do
if ((i%3==0))
then
echo 'Fizz'
else
echo $i
fi
done
In many ways bash is simpler than most other languages but that makes it harder to work with when you are used to "higher" level languages.
So, to help out anyone else that's like me and just starting to code with bash, here is the full program I made, with comments as to why I coded it the way I did. If there are errors in my explanation or my formatting style, please point them out. Thanks! This was kind of fun to write, call me crazy.
# This will literally just print the string inside the single quotes on the screen
echo 'Try running this again but with something like this: fizzbuzz 25 pot kettle black'
# The $0 is the first index, in other words the file name of the executable,
# this will set the default value of x to 20 but will allow the user to input
# something else if they want.
x=${1:-20}
# This is the same but with string variables
f=${2:-FizzBuzz}
g=${3:-Fizz}
b=${4:-Buzz}
# We start the index variable at 1 because it's based on the input,
# otherwise it would echo 0 thru 19
for ((i=1;i<=x;1++))
do
# I recommend using (( )) for if statement arithmetic operations
# since the syntax is similar to other programming languages
if ((i%3==0 && i%5==0)); then echo $f
# you need to use a semicolon to separate if and then if they are
# on the same line, otherwise you can just go to the next line for
# your then statement
else if ((i%3==0)); then echo $g
else if ((i%5==0)); then echo $b
else echo $1
# You need fi in order to finish an if then statement
fi fi fi
done

Comparing two sets of variables line by line in unix, code only prints out the very last line

this is my first stackoverflow question, regarding bash scripting. I am a beginner in this language, so be kind with me.
I am trying to write a comparison script. I tried to store all the outputs into variables, but only the last one is stored.
Example code:
me:1234567
you:2345678
us:3456789
My code:
#!bin/bash
while read -r forName forNumber
do
aName="$forName"
echo "$aName"
aNumber="$forNumber"
echo "$aNumber"
done < "exampleCodeFile.txt"
echo "$aNumber"
For the first time, everything will be printed out fine. However, the second echo will only print out "3456789", but not all the numbers again. Same with $aName. This is a problem because i have another file, which i stored a bunch of numbers to compare $aNumber with, using the same method listed above, called $aMatcher, consisting:
aMatcher:
1234567
2345678
3456789
So if i tried to run a comparison:
if [ "$aNumber" == "$aMatcher" ]; then
echo "match found!"
fi
Expected output (with bash -x "scriptname"):
'['1234567 == 1234567']'
echo "match found!"
Actual output (with bash -x "scriptname"):
'['3456789 == 3456789']'
echo "match found!"
Of course my end product would wish to list out all the matches, but i wish to solve my current issue before attempting anything else. Thanks!
When you run your following code
aNumber="$forNumber"
You are over-writing the variable $aNumber for every line of the file exampleCodeFile.txt rather than appending.
If you really want the values to be appended, change the above line to
aNumber="$aNumber $forNumber"
And while matching with $aMatcher, you again have to use a for/while loop to iterate through every value in $aNumber and $aMatcher.

While loop in .sh file with condition to compare if a string contains a substring

I have a .sh file in which I have written the following function. The command that calls this function will have the arguments- file1.war, file2.war ... fileN.war and other arguments.
I want to do a certain operation to the .war files and something else for the arguments after it. So I have written a while loop that will run till the arguments are .war files, and when an argument is encountered without .war extention, it will exit the loop and run the code below it for the rest of the arguments.
Here is the function in .sh file :
copyWarFiles()
{
downloadFileName=$1
shift 1
extn=".war"
while [ condition ]
do
log "war file $downloadFileName .."
#some operation..
downloadFileName=$1
shift 1
done
#operations for the rest of the arguments...
}
What should I give as condition that will return true if $downloadFileName ends with .war? I tried giving
$downloadFileName==*".war" (following the accepted answer in this )
and I also tried this :
`test "${downloadFileName#*$extn}" != "$downloadFileName"`
(following the accepted answer here) where extn is another variable I declared and assigned to .war.
But in both the cases, I see that it never enters the while loop. I think I have gone wrong with the syntax or something. Thank you for your help in advance.
What should I give as condition that will return true if $downloadFileName ends with ".war"? I tried giving $downloadFileName==*".war" […]
Bash, unlike typical programming languages, doesn't recognize == as a special operator; it's just yet another argument to the [ command. So you need to set it off with spaces.
Also, the [ command doesn't support having a pattern on the right-hand-side of ==; you need to use the special [[ ... ]] notation.
So:
while [[ $downloadFileName == *".war" ]]
Note, though, that the double-quotes around .war don't actually have any effect: none of the characters in .war are special characters that need to be quoted. Conversely, it's a best practice to always put variable expansions in double-quotes, in case the variables contain special characters. ([[ actually negates most of the problematic behaviors, but it's just a good habit to be in.)
So:
while [[ "$downloadFileName" == *.war ]]
Why not just:
check=`echo $downloadFile | grep '\.war'`
if [ -n "$check" ]; then
echo $downloadFile ends in .war
fi

Error: =: command not found (Bash Script)

I found a nifty little shell script that I wanted to use from this website here. I have followed everything step-by-step, but receive the following error when running this on my CentOS box.
./deploy: line 3: =: command not found
Line 3 only contains...
$ERRORSTRING = "Error. Please make sure you've indicated correct parameters"
I've tried toying around with a bit, but don't understand why it won't accept the "=" character. Is there something wrong with the script, or is it merely something different in the way that my server processes the script?
Thanks!
Gah, that script is full of bad scripting practices (in addition to the outright error you're running into). Here's the outright error:
$ERRORSTRING = "Error. Please make sure you've indicated correct parameters"
As devnull pointed out, this should be:
ERRORSTRING="Error. Please make sure you've indicated correct parameters"
A couple of lines down (and again near the end), we have:
echo $ERRORSTRING;
...which works, but contains two bad ideas: a variable reference without double-quotes around it (which will sometimes be parsed in unexpected ways), and a semicolon at the end of the line (which is a sign that someone is trying to write C or Java or something in a shell script). Use this instead:
echo "$ERRORSTRING"
The next line is:
elif [ $1 == "live" ]
...which might work, depending on whether the value of $1 has spaces, or is defined-but-blank, or anything like that (again, use double-quotes to prevent misparsing!). Also, the == comparison operator is nonstandard -- it'll work, because bash supports it in its [ ... ] builtin syntax, but if you're counting on having bash extensions available, why not use the much cleaner [[ ... ]] replacement? Any of these would be a better replacement for that line:
elif [ "$1" = "live" ]
elif [[ $1 == "live" ]]
elif [[ "$1" == "live" ]]
Personally, I prefer the last. The double-quotes aren't needed in this particular case, but IMO it's safest to just double-quote all variable references unless there's a specific reason not to. A bit further down, there's a elif [ $2 == "go" ] that the same comments apply to.
BTW, there's a good sanity-checking tool for shell scripts at www.shellcheck.net. It's not quite as picky as I am (e.g. it doesn't flag semicolons at the ends of lines), but it pointed out all of the actual errors in this script...
"Devnulls" answer was correct -- I had to remove the spaces around the "=" and remove the "$" from that line as well. The end result was...
ERRORSTRING="Error. Please make sure you've indicated correct parameters"
I've upvoted Devnull and gniourf_gniourf's comments.
Thank you to all whom have assisted!

Resources