I did use the manual but I am unable to get all the options together to understand what the above code is actually doing.
awk -v v='"' 'BEGIN{FS=OFS=v}{gsub(",","",$2);print }' \
${SOURCE_LOCATION}/TEMP1_$file_name>${SOURCE_FILE_LOCATION}/TEMP2_$file_name
When do we have to use the curly brackets in a code after the '$' and when not to. Please explain. Any help is really appreciated.
This command would remove all the commas in the second field. The field separator being the quote character " (as specified by FS).
For example, the following string:
something "string, with, commas" something "else, here, and more"
would be transformed to:
something "string with commas" something "else, here, and more"
The significance of {} in variable names has been well explained by #Joni.
The input is read from the file ${SOURCE_LOCATION}/TEMP1_$file_name and output is redirected to ${SOURCE_LOCATION}/TEMP2_$file_name.
You must use the curly brackets syntax when a variable name is followed by something that's not part of the variable name but could be confused with it. For example, compare
hello="Hello"
echo $hello_world
with
hello="Hello"
echo ${hello}_world
The first one outputs an empty line (or the value of the shell variable hello_world, if it exists), and the second one outputs Hello_world.
In your case they are not necessary because a slash can never be a part of the variable name. Some people prefer to use the brackets to make it clear where the variable begins and where it ends even when they are not required.
Related
echo 'Text\n' >\*\\'"Text in Here"\'\\*$\?\*\*\*\*\*:)
I want to write that file name but it seems like it's impossible to do with these blackslashes
You are just missing a back slash to escape the last bracket
echo 'Text\n' >\*\\'"Text in Here"\'\\*$\?\*\*\*\*\*:\)
EDIT: I didn't see you actually wanted all those backslashes in the name. In that case you need
echo 'Text\n' > \\\*\\\\\'\"Text in Here\"\\\'\\\\\*\$\\\?\\\*\\\*\\\*\\\*\\\*:\)
Don't bother trying to escape individual characters. Limit the special characters you need to worry about by using single quotes. Then, the single quote is the only character you need to worry about, and you get it by enclosing it in double quotes. Eg:
echo 'Text\n' > '\*\\'"'"'"Text in Here"\'"'"'\\*$\?\*\*\*\*\*:)'
Better yet, choose a simpler name. :)
I'm trying to create function that will print message bound to variable in certain color. The message variable is passed as argument of this function. The problem is that I'm getting only text up to first space (only first word of message). My script looks like this:
#!/usr/bash
lbGREEN='\e[1;92m'
NC='\e[0m'
normalMessage="Everything fine"
echo_message() {
echo -e ${lbGREEN}$1${NC}
}
echo_message $normalMessage
My output is:
Everything
As Inian pointed out in comments, your problem is unquoted variable expansion
echo_message $normalMessage
becomes
echo_message Everything fine
once the variable expands, meaning that each word of your input string is getting read in as a separate argument. When this happens $1=Everything and $2=fine.
This is fixed by double-quoting your variable, which allows expansion, but will mean the result of the expansion will still be read as one argument.
echo_message "$normalMessage"
becomes
echo_message "Everything fine"
Like this $1=Everything fine
In the future, I recommend using https://www.shellcheck.net/, or the CLI version of shellcheck, it will highlight all kinds of common bash gotcha's, included unquoted expansion.
For me, I had to change the header for "#!/bin/bash", but apparently that is not the problem for you.
In your echo you are printing only the first word with the $1, if you change it to $2 you will print the second word (parameter) and so on.
You can pass the name inside quotes or print all the parameters with $#
Solution 1 (with $#):
lbGREEN='\e[1;92m'
NC='\e[0m'
normalMessage="Everything fine"
echo_message() {
echo -e ${lbGREEN}$#${NC}
}
echo_message $normalMessage
Solution 2 (with quotes):
lbGREEN='\e[1;92m'
NC='\e[0m'
normalMessage="Everything fine"
echo_message() {
echo -e ${lbGREEN}$1${NC}
}
echo_message "$normalMessage"
You should get a look to https://stackoverflow.com/a/6212408/1428602
IMHO, $1 only return the 1st word, so you have to use a loop or try with $*
You've got the quoting wrong.
If you want to simulate the behaviour of echo, your function should accept multiple parameters, and print them all. Currently it's only evaluating the first parameter, so I suggest using $* instead. You also need to enclose the argument in double quotes to protect any special characters:
echo_message() {
echo -e "${lbGREEN}$*${NC}"
}
The special variable $* expands to all the arguments, separated by spaces (or more accurately, the first character of $IFS, which is usually a space character). Note that you almost always want "$#" instead of "$*", and this is one of the rare occasions where the latter is also correct, though with slightly different semantics if IFS is set to a non-standard value.
Now the function supports multiple arguments, and prints them all in green, separated by spaces. However, I would recommend that you also quote the argument when calling the function:
echo_message "$normalMessage"
While spaces in $normalMessage will now be treated correctly, other special characters like ! will still require the quotes.
Writing a small script in bash (MacOS in fact) and I want to use find, with multiple sources. Not normally a problem, but the list of source directories to search is held as a string in a variable. Again, not normally a problem, but some of them contain spaces in their name.
I can construct the full command string and if entered directly at the command prompt (copy and paste in fact) it works as required and expected. But when I try and run it within the script, it flunks out on the spaces in the name and I have been unable to get around this.
I cannot quote the entire source string as that is then just seen as one single item which of course does not exist. I escape each space with a backslash within the string held in the variable and it is simply lost. If I use double backslash, they both remain in place and again it fails. Any method of quoting I have tried is basically ignored, the quotes are seen as normal characters and splitting is done at each space.
I have so far only been able to use eval on the whole command string to get it to work but I felt there ought to be a better solution than this.
Ironically, if I use AppleScript I CAN create a suitable command string and run it perfectly with doShellScript (ok, that's using JXA, but it's the same with actual AppleScript). However, I have so far been unable to find the correct escape mechanism just in a bash script, without resorting to eval.
Anyone suggest a solution to this?
If possible, don't store all paths in one string. An array is safer and more convenient:
paths=("first path" "second path" "and so on")
find "${paths[#]}"
The find command will expand to
find "first path" "second path" "and so on"
If you have to use the string and don't want to use eval, split the string into an array:
string="first\ path second\ path and\ so\ on"
read -a paths <<< "$string"
find "${paths[#]}"
Paths inside string should use \ to escape spaces; wraping paths inside"" or '' will not work. eval might be the better option here.
I'm having an extremely hard time figuring out how to echo this:
![alt text](https://github.com/adam-p/markdown-here/raw/master/src/common/images/icon48.png "Logo Title Text 1")
I keep getting this error:
bash: ![alt: event not found
Using double quotes around it does not work. The using single quotes around it does work, however, I also need to echo strings that have single quotes within them. I wouldn't be able to wrap the string with single quotes then.
Is there a way to echo a string of ANY content?
Thanks.
EDIT: Here is some context. I am making a Markdown renderer that grabs the content of a code editor, then appends every line of the code individually into a text file. I am doing this by doing this:
echo TheLineOfMarkdown > textfile.txt
Unlike in many programing languages, '...' and "..." in Bash do not represent "strings" per se; they quote/escape whatever they contain, but they do not create boundaries that separate arguments. So, for example, these two commands are equivalent:
echo foobar
echo "fo"ob'ar'
So if you need to quote some of an argument with single-quotes, and a different part of the argument has to contain single-quotes — no problem.
For example:
echo '![alt text](https://... "What'"'"'s up, Doc?")'
Another option is to use \, which is similar to '...' except that it only quotes a single character. It can even be used inside double-quotes:
echo "\![alt text](https://... \"What's up, Doc?\")"
For more information, see §3.1.2 "Quoting" in the Bash Reference Manual.
! is annoying. My advice: Use \!.
! invokes history completion, which is also performed inside double-quotes. So you need to single-quote the exclamation mark, but as you say that conflicts with the need to not single-quote other single-quotes.
Remember that you can mix quotes:
$ echo '!'"'"'"'
!'"
(That's just one argument.) But in this case, the backslash is easier to type and quite possibly more readable.
I have the following command
cmd '"asdf" "a'sdf"'
I need to surround the arguments with single quotes only. cmd doesnt work with double quotes for some reason I dont know. The above command doesnt work because the single in the middle terminates the first single quote. If I escape, to the following
cmd '"asdf" "a\'sdf"'
It still doesnt work. How do I get this working?
According to the bash man page:
Enclosing characters in single quotes preserves the literal value
of each character within the quotes. A single quote may not occur
between single quotes, even when preceded by a backslash.
So the answer is, you can't include a single quote within a single-quoted string no matter how you try. But depending on how your script is set up you may be able to use '\'', which will end the first single quote, escape the second, and start another single-quoted string with the third.
A long long time ago, a mentor suggested I use constructs like '"asdf" "a'"'"'sdf"'. It works, but it's bizarre to look at.
Since you can't put single quotes inside single quotes, escaping them like '"asdf" "a'\''sdf' may be the way to go.
Note that you can also use printf and variables interactively or within a shell script. With most shells (you haven't specified what you're using), you should get the similar results to this:
$ fmt='"asdf" "a%ssdf"\n'
$ printf "$fmt" "'"
"asdf" "a'sdf"
$
or you could even include the single quote using its ASCII value:
$ fmt='"asdf" "a\047sdf"\n'
$ printf "$fmt"
"asdf" "a'sdf"
$
or in csh:
% set fmt='"asdf" "a\047sdf"\n'
% printf "$fmt"
"asdf" "a'sdf"
%
This is shell-independent because if your shell doesn't have a printf command built in (as Bash has), then the command will most likely exist as a separate binary in /bin or /usr/bin.
I don't know your use case, so it's difficult to come up with a solution that I know will be applicable.
Well, you can always use autocomplete to help you find the answer.
For instance, if I have a file with an apostrophe in it, but I want to surround the path with single quotes, I can do this (using cat as an example command where the file is named sam's file.txt):
cat 'sam[press tab here]
and it autocompletes to this, for me:
cat 'sam'\''s\ file.txt
So, apparently it is possible. Another answerer mentioned the '\'' thing first, but I figured I'd tell you one way to try to figure it out if that's not working for you (and I thought I'd be another witness to tell you the other answer seems to work).