what is ":" called in bash? Colon usage as a pass statement [duplicate] - bash

This question already has answers here:
What is the purpose of the : (colon) GNU Bash builtin?
(12 answers)
Closed 8 years ago.
See: What is the Bash equivalent of Python's pass statement
What is this ":" colon usage called? For example:
if [[ -n $STRING ]]; then
#printf "[INFO]:STRING: if -n string: STRING:$STRING \n"
:
else
printf "[INFO]:Nothing in the the string\n"
fi

To what that is, run help : in the shell. It gives:
$ help :
:: :
Null command.
No effect; the command does nothing.
Exit Status:
Always succeeds.
Very useful in one-liner infinite loops, for example:
while :; do date; sleep 1; done
Again, you could write the same thing with true instead of :, but this is shorter.
Interestingly:
$ help true
true: true
Return a successful result.
Exit Status:
Always succeeds.
According to this, the difference is that : is "Null command",
while true is "Returns a successful result".
Another difference is that true is usually a real binary:
$ which true
/usr/bin/true
On the other hand, which : gives nothing. (Which makes sense, being a "null command".)
Anyway, #Andy is right, this is duplicate of this other post, which explains it much better.

Related

Replace substring in string [duplicate]

This question already has answers here:
Search+replace strings in filenames
(2 answers)
How do I set a variable to the output of a command in Bash?
(15 answers)
Command not found error in Bash variable assignment
(5 answers)
Closed 1 year ago.
i have just tried to one of my first bash scripts, i need to find a substring(after the ? part) in a url and replaced with the replace_string,
#!/bin/bash
url="https://example.com/tfzzr?uhg"
# 123456 ...
first= echo `expr index "$url" ?`
last= expr length $url
replace_string="abc"
part_to_be_replace = echo ${url:($first+1):$last}//dont know how to use variable here
substring(url,part_to_be_replace,replace_string)
It does not work, i was able to find only the first accurance of ?, and the length of the string
Does this help?
url="https://example.com/tfzzr?uhg"
replace_string="abc"
echo "${url}"
https://example.com/tfzzr?uhg
echo "${url//\?*/${replace_string}}"
https://example.com/tfzzrabc
# If you still want the "?"
echo "${url//\?*/\?${replace_string}}"
https://example.com/tfzzr?abc
See https://www.gnu.org/software/bash/manual/html_node/Shell-Parameter-Expansion.html for further details.
Use parameter expansion:
#! /bin/bash
url='https://example.com/tfzzr?uhg'
replace_string=abc
new=${url%\?*}?$replace_string
echo "$new"
${url%\?*} removes the pattern (i.e. ? and anything following it) from $url. ? needs to be quoted, otherwise it would match a single character in the pattern. Double the percent sign to remove the longest possible substring, i.e. starting from the first ?.

Is it possible to force bash to do an in-place expansion of a variable whose value contains quotes? [duplicate]

This question already has answers here:
Reading quoted/escaped arguments correctly from a string
(4 answers)
Why does shell ignore quoting characters in arguments passed to it through variables? [duplicate]
(3 answers)
Closed 1 year ago.
Consider the following simple function.
X() {
echo "$1"
echo "$2"
echo "$3"
}
Now consider the following variable:
args="-H 'h1 : v1'"
When I run the command X $args, I get the following output:
-H
'h1
:
On the other hand, if I run the command X -H 'h1 : v1', I get the following output:
-H
h1 : v1
Note that, in the latter case, the quotes inside the variable's value are correctly interpreted as delimiters.
Is it possible to modify either the declaration of the variable or the invocation with a variable to force the two outputs above to be equivalent?
This is what arrays are for.
$ args=(-H 'h1: v1')
$ printf '%s\n' "${args[#]}"
-H
h1 : v1

How to convert bash shell string to command [duplicate]

This question already has answers here:
How can I store a command in a variable in a shell script?
(12 answers)
Dynamic variable names in Bash
(19 answers)
Closed 1 year ago.
I am running different program with different config. I tried to convert string (kmeans and bayes) in the inner loop to variables I defined at the beginning, so I can run the programs and capture the console output. kmeans_time and bayes_time are used to record execution time of each program.
#!/bin/bash
kmeans="./kmeans -m40 -n40 -t0.00001 -p 4 -i inputs/random-n1024-d128-c4.txt"
bayes="./bayes -t 4 -v32 -r1024 -n2 -p20 -s0 -i2 -e2"
kmeans_time=0
bayes_time=0
for n in {1..10}
do
for prog in kmeans bayes
do
output=($(${prog} | tail -1))
${$prog + "_time"}=$( echo $kmeans_time + ${output[1]} | bc)
echo ${output[1]}
done
done
However, I got the following errors. It seems that the prog is executed as a string instead of command I defined. Also, concatenation of the time variable filed. I've tried various ways. How is this accomplished in Bash?
./test.sh: line 11: kmeans: command not found
./test.sh: line 12: ${$app + "_time"}=$( echo $kmeans_time + ${output[1]} | bc): bad substitution
What I am trying to do is to execute as follow, which can work properly.
kmeans="./kmeans -m40 -n40 -t0.00001 -p 4 -i inputs/random-n1024-d128-c4.txt"
output=($($kmeans | tail -1))
# output[1] is the execution time
echo "${output[1]}"
kmeas_times=$kmeans_times+${output[1]}
I want to iterate over different programs and calculate each of their average execution time
I am vaguely guessing you are looking for printf -v.
The string in bayes is not a valid command, nor a valid sequence of arguments to another program, so I really can't guess what you are hoping for it to do.
Furthermore, output is not an array, so ${output[1]} is not well-defined. Are you trying to get the first token from the line? You seem to have misplaced the parentheses to make output into an array; but you can replace the tail call with a simple Awk script to just extract the token you want.
Your code would always add the value of kmeans_time to output; if you want to use the variable named by $prog you can use indirect expansion to specify the name of the variable, but you will need a temporary variable for that.
Mmmmaybe something like this? Hopefully this should at least show you what valid Bash syntax looks like.
kmeans_time=0
bayes_time=0
for n in {1..10}
do
for prog in kmeans bayes
do
case $prog in
kmeans) cmd=(./kmeans -m40 -n40 -t0.00001 -p 4 -i inputs/random-n1024-d128-c4.txt);;
bayes) cmd=(./bayes -t 4 -v32 -r1024 -n2 -p20 -s0 -i2 -e2);;
esac
output=$("${cmd[#]}" | awk 'END { print $2 }')
var=${prog}_time
printf -v "$var" %i $((!var + output))
echo "$output"
done
done
As an alternative to the indirect expansion, maybe use an associative array for the accumulated time. (Bash v5+ only, though.)
If running the two programs alternatingly is not important, your code can probably be simplified.
kmeans () {
./kmeans -m40 -n40 -t0.00001 -p 4 -i inputs/random-n1024-d128-c4.txt
}
bayes () {
./bayes -t 4 -v32 -r1024 -n2 -p20 -s0 -i2 -e2
}
get_output () {
awk 'END { print $2 }'
}
loop () {
time=0
for n in {1..10}; do
do
output=("$#" | get_output)
time=$((time+output))
print "$output"
done
printf -v "${0}_time" %i "$time"
}
loop kmeans
loop bayes
Maybe see also http://mywiki.wooledge.org/BashFAQ/050 ("I'm trying to put a command in a variable, but the complex cases always fail").

Bash: Check a String is a Number (whatever the format) [duplicate]

This question already has answers here:
How do I test if a variable is a number in Bash?
(40 answers)
Closed 2 years ago.
I would like to share a way to check a string is a number in bash. This question has already been asked here, but the answer fits only for either integers or floats in classical format, when a number can be in scientific format, and it uses complex regex. Second, I don't have enough reputation to answer the existing question (totally fresh account here...).
So the question is:
How to (Easily) Check a String is a Number in bash?
with the string being like:
"1234"
"-1.234"
"1.23e4"
"+1.23E04"
etc.
Answer in the... answer below.
An easy way is to use awk like this:
function IsNumber {
echo "$1" | awk '{if ($1+0 == $1) print "true"; else print "false"}'
}
Examples:
$ IsNumber 1234
true
$ IsNumber 1.234
true
$ IsNumber 1.23E04
true
$ IsNumber abc
false

Why my bash if condition is not considering second condition? [duplicate]

This question already has answers here:
How to handle more than 10 parameters in shell
(2 answers)
Closed 3 years ago.
I have got the following code snippet.
if [ "$2" == "azure" ] && [ -n $11 ]; then
CRED_KIND=$2
CRED_NAME=$3
CRED_UNAME=$4
CRED_PWD=$5
TWR_UNAME=$6
TWR_PWD=$7
CLNT=$8
SEC=$9
SUBS=$10
TEN=$11
credsplaybook $CRED_KIND $CRED_NAME $CRED_UNAME $CRED_PWD $TWR_UNAME $TWR_PWD $CLNT $SEC $SUBS $TEN
exit 1
fi
For some reason, even when i pass only 7 arguments, it keeps executing the if condition considering only first check and skips the second one. As per the condition, it should check if the second argument is "azure" and whether a total of 11 arguments are passed.
./createResourcesPlaybook.sh cred azure test123 myuser mypass tower towerpass
[INFO] Creating Playbook for Credential with type azure
.
.
.
rest of output
[ "$2" == "azure" ] && [ -n $11 ] are two unrelated commands chained together, the second only is executed if the first is "true".
Also, and as mentioned by others, double-digit (or more) positional argument variables needs to be enclosed in braces. So $11 needs to be ${11}.
And the -n option to the test command ([ is an alias of test) is to check if a string is empty or not but if ${11} doesn't exist then it's not equal to an empty string but rather nothing at all, making the -n check invalid.
To solve both these problems use the -a option for logical and of two conditions, and use double-quotes to make ${11} a string:
if [ "$2" == "azure" -a -n "${11}" ]

Resources