How to encase a command line argument in quotes with a bash/shell script [duplicate] - bash

This question already has answers here:
How do I pass in the asterisk character '*' in bash as arguments to my C program?
(5 answers)
The issue of * in Command line argument
(6 answers)
Closed 5 years ago.
How do I write a bash script/function that will take a command line argument with spaces and interpret it as if it had quotes around it.
ie: echo this is some text as if echo "this is some text"
What I want to do is create a simple CLI calculator script/function.
Here is what I have:
calc() {
echo $(($#))
}
On the CLI, all of these work:
"# +-/* ", #+-/*, # +-/ #
ie:
calc 10+2
12
but this one produces an error:
calc 10 * 2
-bash: 10 calc.sh 2: syntax error: invalid arithmetic operator (error token is ".sh 2")
Any ideas? It's not a big deal to include the quotes in the calculations, but if possible it would be quicker/more convenient to not include them. Is there any way to take a string after calc from first character to last and then pass it through quotes in the script?

In unix systems there is a variable called IFS. This variable decides at what signs the console separate the string into words. In theory you could chang the IFS variable, but this is really not advisable (as it will breake other bash commands).
Better: you could write your utillity in such way, that writing 'calc' will prompt the user to type his equation to standard in. Then you can read the text the user types and parse it in any way you want.
Even better: a shell script can specify that it wishes for an arbitrary nimber of words as input. Take all the words the user writes and then parse that. See: How to define a shell script with variable number of arguments?

Related

Prevent variable expansion in Bash heredocument [duplicate]

This question already has answers here:
How to cat <<EOF >> a file containing code?
(5 answers)
Using variables inside a bash heredoc
(3 answers)
Escaping a dollar sign in Unix inside the cat command
(2 answers)
How to split strings over multiple lines in Bash?
(12 answers)
Closed 4 months ago.
I would like to create a longer multiline string in Bash without variable expansion. This text contains also items like ${varname} which is expanded according to the specification. However, I don't want to expand them in my script.
Dockerfile=`cat <<____
ARG BUILD_IMAGE
FROM ${BUILD_IMAGE}
...
# lots of further lines
____
`
I tried several variants ($\{, $\0173), but I could only solve it with
b='${'
...
FROM ${b}BUILD_IMAGE}
...
Which is really ugly. Is there any better way to solve this?
Edit:
Dockerfile=`cat <<'____'
ARG BUILD_IMAGE
FROM ${BUILD_IMAGE}
...
# lots of further lines
____
`
would solve the issue, but in this case I can't use any variable expansion.
Edit 2 - Answer:
Since the post has been closed, I answer my question here:
There is a difference between using backquote and $(. The issue is solved if I use the latter one. I had the problem, because I used the former one.
When the old-style backquote form of substitution is used, backslash
retains its literal meaning except when followed by $, `, or . The
first backquote not preceded by a backslash terminates the command sub‐
stitution. When using the $(command) form, all characters between the
parentheses make up the command; none are treated specially.
This means in praxis:
text=$(cat <<__EOT__
Hello ${who}, hello \${who}!
__EOT__
)
echo $text
text=`cat <<__EOT__
Hello ${who}, hello \${who}!
__EOT__
`
echo $text
results in
Hello World, hello ${who}!
Hello World, hello World!

What does the #*$ in a shell script's string interpolation do? [duplicate]

This question already has answers here:
What is the meaning of the ${0##...} syntax with variable, braces and hash character in bash?
(4 answers)
Closed 11 months ago.
I found the following code in a shell script, but I am unsure of what the test condition is evaluating for
if test "${SOME_VAR#*$from asdf/qwer}" != "$SOME_VAR"; then
echo "##zxcv[message text='some text.' status='NORMAL']";
fi
The combination #*$ does not mean anything special. There are three special symbols and each of them has its own meaning in this context.
${SOME_VAR#abc} is a parameter expansion. Its value is the value of $SOME_VAR with the shortest prefix that matches abc removed.
In your example, abc is *${from} asdf/qwer. That means anything * followed by the value of variable $from (which is dynamic and replaced when the expression is evaluated), followed by a space and followed by asdf/qwer.
All in all, if the value of $SOME_VAR starts with a string that ends in ${from} asdf/qwer then everything before and including asdf/qwer is removed and the resulting value is passed as the first argument to test.
Type man bash in your terminal to read the documentation of bash or read it online.

reference a bash variable within a command using $() [duplicate]

This question already has answers here:
Assignment of variables with space after the (=) sign?
(4 answers)
Closed 3 years ago.
#!/bin/bash
declare -r NUM1=5
NUM2 =4 # Line 4
num3=$((NUM1 + NUM2))
num4=$((NUM1 - NUM2))
num5=$((NUM1 * NUM2))
num6=$((NUM1 / NUM2)) # Line 9
echo "$num3"
echo $((5**2))
echo $((5%4))
I am using this bash script, and when I was running the script, I got the error
./bash_help
./bash_help: line 4: NUM2: command not found
./bash_help: line 9: NUM1 / NUM2: division by 0 (error token is "NUM2")
5
25
1
So I have changed the code to this and the error was gone.
#!/bin/bash
declare -r NUM1=5
NUM2=4
num3=$((NUM1 + NUM2))
num4=$((NUM1 - NUM2))
num5=$((NUM1 * NUM2))
num6=$((NUM1 / NUM2))
echo "$num3"
echo $((5**2))
echo $((5%4))
Why can't we use spaces when we assign a value to a variable? It is convention to use spaces for better readability of the code. Can anyone explain this?
It's not a convention in bash (or, more generally, POSIX-family shells).
As for "why", that's because the various ways of doing it wrong all have valid meanings as commands. If you made NUM2 = 4 an assignment, then you couldn't pass = as a literal argument without quoting it. Consequently, any such change would be backwards-incompatible, rather than being placed in undefined space (where extensions to the POSIX sh standard need to live to avoid constituting violations of that standard).
NUM2= 4 # runs "4" as a command, with the environment variable NUM2 set to an empty string
NUM2 =4 # runs "NUM2" as a command, with "=4" as its argument
NUM2 = 4 # runs "NUM2" as a command, with "=" as its first argument, and "4" as another
In Bash, functions are passed arguments as whitespace separated words.
From the documentation
"Each operator and operand must be a separate argument."
Variable assignment is different and uses this syntax name=[value]
The reason you can't put unquoted spaces around the equals sign is because bash would interpret this as a command.
The reason is, quite simply, that the shell is built to behave like this. It may not make sense for someone with experience in other programming languages (if you call shell syntax a "language", which in a sense it is).
Shell scripting makes it possible in many cases to simply not quote strings (as long as a sequence of characters meant to be a single string does not contain any spacing or special characters). Thanks to this, you can write :
my_command -n -X arg1 arg2
Instead of (in some kind of imaginary pseudo code)
"my_command" "-n" "-X" "arg1" "arg2"
In most languages, it is the other way around : literal strings are quoted, which frees "syntax space" for using variables without any special character (like $ in shell scripting).
Shell syntax provides convenience in frequent cases, at the cost of, well, less convenience (and readability) when doing some other things. It is both a curse and a blessing. The nice thing is knowing that if you have an interactive shell, you can be 100% sure you have an interpreter that will handle some kind of (maybe inelegant) programs. Due to its universal availability (despite various flavors being in existence), the shell is a kind of platform that is useful enough to be worth learning.

BASH remove specific tokens from a word [duplicate]

This question already has answers here:
Command not found error in Bash variable assignment
(5 answers)
Closed 5 years ago.
I am trying to find te longest word in a given file. Before I check the lengtgh of each word I need to remove all of the following tokens {,.:} that may be attached (once or more) to the word. so for example, for this text:
:,cat dog, encyclopedia; remove:.,
i need the result:
cat dog encyclopedia remove
I am trying this, but I get a "command not found":
longest=0
for word in $(<$1)
do
#new_word = $(echo "${word//[.,:]/}")
new_word = "${word//[.,:]/}"
len=${#new_word}
if (( len > longest ))
then
longest=$len
longword=$new_word
fi
done
echo The longest word is $longword and its length is $longest.
thank you.
Your use of parameter expansion replacement pattern is correct.
The problem is that there must not be any whitespace around = while declaring variables in bash (any shell in general).
So, the following should work:
new_word="${word//[.,:]/}"
As an aside, use a while read ... construct to loop over the lines in a file, using for is pretty fragile.

bash script whole file reading into a variable with newline [duplicate]

This question already has answers here:
I just assigned a variable, but echo $variable shows something else
(7 answers)
Closed 7 years ago.
i want to read whole file in a variable.
for example my file is.
file name : Q.txt
My name is Naeem Rehmat.
I am a student of FAST university.
Now i am in 4th semester.
I am learning bash script.
I have this problem.
code:
text=$(cat Q.txt)
echo $text
out put should be like this:
My name is Naeem Rehmat.
I am a student of FAST university.
Now i am in 4th semester.
I am learning bash script.
I have this problem.
Presumably the problem is that your whitespace is incorrect. Use double quotes:
echo "$text"
When you write echo $text without quotes, bash evaluates the string and performs what is known as "field splitting" or "word splitting" before generating the command. To simplify the case, suppose text is the string foo bar. Bash splits that into two "words" and passes "foo" as the first argument to echo, and "bar" as the second. If you use quotes, bash passes only one argument to echo, and that argument contains multiple spaces which echo will print.
Note that it is probably good style to also use quotes in the assignment of text (ie, text="$(cat Q.txt)"), although it is not necessary since field splitting does not occur in a variable assignment.

Resources