What do square brackets mean in the documentation? [duplicate] - bash

This question already has answers here:
Linux/Unix 'man' page syntax conventions
(2 answers)
What does "[]" or "<>" mean in some command document? [duplicate]
(1 answer)
Closed 1 year ago.
How do I interpret square brackets? For example:
The syntax of the 'case' command is:
case WORD in
[ [(] PATTERN [| PATTERN]...) COMMAND-LIST ;;]...
esac
I understand how to do the loop but when asking for help from bash documentation I did not know how to interpret the brackets. I mean what the hell does it mean, [(]?

The syntax of bash compound commands is defined using the man page synopsis conventions. These are defined in man(1):
The following conventions apply to the SYNOPSIS section and can be used
as a guide in other sections.
bold text type exactly as shown.
italic text replace with appropriate argument.
[-abc] any or all arguments within [ ] are optional.
-a|-b options delimited by | cannot be used
together.
argument ... argument is repeatable.
[expression] ... entire expression within [ ] is repeatable.

Related

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.

Why does * put all file names in the argument vector? [duplicate]

This question already has answers here:
What is file globbing?
(1 answer)
Stop shell wildcard character expansion?
(4 answers)
command line * linux [duplicate]
(1 answer)
Closed 4 years ago.
I stumbled upon this while working through the exercises in K&R2. Why does echo * prints the names of all files in the current directory? More generally, when I write a C program that takes command-line arguments, and when I give it * as an argument, it puts the names of all files in its parent directory in to the argument vector. Why does this happen? What is so special about *?
I could not find anything about this in the internet.
This is called globbing. Here's a detailed description. Other wildcards include ? for one character, [abc] for one of a set of characters, and [a-z] for one of a range of characters. This is built into various shells, including Bash.
In response to your comment "I think echo is written in C" — this doesn't matter a bit. Once source code is compiled into an executable containing machine code, it doesn't matter what language it was written in.

Why is a separator not required in `for i do cmd; done` [duplicate]

This question already has an answer here:
Is a semicolon prohibited after NAME in `for NAME do ...`?
(1 answer)
Closed 4 years ago.
for i do echo $i; done
How is this even legal? (I would expect it to be written with an extra semi-colon for i; do echo $i; done) It works in bash, dash, zsh, and ksh. The standard (by which I mean http://pubs.opengroup.org/onlinepubs/9699919799/) states:
The for loop requires that the reserved words do and done be used to
delimit the sequence of commands. The format for the for loop is as follows:
for name [ in [word ... ]]
do
compound-list
done
So clearly when "in word" is omitted, do is serving as a separator. So the implication seems to be that the separator (the newline) after the [ in [word .. ]] actually belongs inside the closing right bracket. Can someone point to anything in the standard which justifies this (IMO) horrible abuse of the language?
If you look at the GNU man page, you see the loop has this syntax:
for
The syntax of the for command is:
for name [ [in [words …] ] ; ] do commands; done
So as you can see the extra semi-colon is part of the optional section.
The linux-die man page states the same.
Perhaps someone else can fill you in on the history of the syntax, but in shell scripting, space characters (by default) are the delimiters. The ; character is just a statement separator. It's often used instead of a newline to write logic as a "one-liner". Semicolons at the end of a line in a shell script are superfluous as both are command separators.
Also worth noting is the bracket syntax above is meant to indicate that those parts of the syntax are optional (i.e. you don't actually use brackets in the script there).
Finally, I find it's good to think of shells as... well, shells. You can write scripts with them and as "languages" they're Turing complete, but the syntax is often kind of funky.

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

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?

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.

Resources