I wrote a bash script which automatically configures a setting file for some application.
The application uses a similar syntax to /etc/sysconfig/network file, the only exception is that it requires the values to be in double quotes " ".
So the line in the script looks something like this, but I don't know how to allow the double quotes of the ip address within the echo:
echo " ipaddr="1.1.1.1" " > file
How can it be done?
Escape the quotes with a backslash character or use single quotes:
echo "ipaddr=\"1.1.1.1\""
echo 'ipaddr="1.1.1.1"'
The other answers all provide excellent ways of solving your problem. I'd just like to add one using printf, that can make things comfortable if, e.g., the ip address is stored in a variable:
ip=1.1.1.1
printf 'ipaddr="%s"\n' "$ip" > file
But here again, as in the other answers, you'll need to play with both, single and double quotes.
Things will be comfortable in this case (still assuming the ip is in the variable ip), because with echo instead of printf, you'd have to use either:
echo "ipaddr=\"$ip\"" > file
# or
echo 'ip addr="'"$ip"'"' > file
(ok, it's not a big deal, but I usually like printf better than echo in bash).
You have at least two options:
Escape the double-quotes with single-quotes:
echo ' ipaddr="1.1.1.1" ' > file
Escape the double-quotes with backslashes:
echo "ipaddr=\"1.1.1.1\"" > file
In general, you can use a backslash to escape any single character; and you can use one type of quote to escape the other.
you got the choice:
you can use different quotes inner and outer of the echo
echo "ipaddr='1.1.1.1'" > file
echo 'ipaddr="1.1.1.1"' > file
you can escape the quotes:
echo "ipaddr=\"1.1.1.1\"" > file
or you can make it simpler (but with escapes on the quotes):
echo ipaddr=\"1.1.1.1\" > file
Related
I mean something like this
<{ any text; "with double quotes"; some $VARIABLE here; and 'single quotes'; and semicolons; } >| doc.txt
we have several quotes types and many nested variables to be solved.
we dont want to escape symbols.
with here-documents, you must have two lines.
with here-string, you must escape all nested quotes.
any logical solution ?
If the currently executed script is an actually existing file, you can get the current line and extract from it the text that you want to preserve, whereas the text may be stored as a comment after a special delimiter. With envsubst you can substitute variable expansions of exported variables. Something along:
sed -n "${BASH_LINENO}s/.*### //p" "$0" | VARIABLE="$VARIABLE" envsubst '$VARIABLE' > doc.txt ### any text; "with double quotes"; some $VARIABLE here; and 'single quotes'; and semicolons;
You could also, in the same fashion, create an eval that would use that line content inside an eval-ed single line generated here-document:
eval "cat <<EOF$(echo)$(sed -n "${BASH_LINENO}s/.*### //p" "$0")$(echo EOF)" > doc.txt ### any text; "with double quotes"; some $VARIABLE here; and 'single quotes'; and semicolons;
With base64 -w0 (or many other encoding) you can encode any script, also multiline, into a single line. Remove echo from below to actually execute the script.
echo eval "$(base64 -d <<<Y2F0IDw8RU9GCmFueSB0ZXh0OyAid2l0aCBkb3VibGUgcXVvdGVzIjsgc29tZSAkVkFSSUFCTEUgaGVyZTsgYW5kICdzaW5nbGUgcXVvdGVzJzsgYW5kIHNlbWljb2xvbnM7CkVPRgo=)" > doc.txt
I have these file names that literally have double quotes in the path to deal with special characters issues, I want to loop through and echo the file paths while preserving the quotes, this seems to remove them:
for value in temp/sample."sample.id1".genotypes.txt temp/sample."sample.id2".genotypes.txt; do echo $value; done
I tried this but no luck:
for value in temp/sample."sample.id1".genotypes.txt temp/sample."sample.id2".genotypes.txt; do echo '${value}'; done
How do I do this?
You need to quote the strings to preserve the double quotes:
for value in 'temp/sample."sample.id1".genotypes.txt' 'temp/sample."sample.id2".genotypes.txt'; do
echo "$value"
done
Otherwise, writing some."thing" is identical to some.thing because the shell interprets the quotes.
You can also escape it :
for value in temp/sample.\"sample.id1\".genotypes.txt temp/sample.\"sample.id2\".genotypes.txt; do echo $value; done
for things like this, I like to use a slightly different approach that looks like a better design to me:
# make an array with the data
mapfile -t ary <<"EOF"
temp/sample."sample.id1".genotypes.txt
temp/sample."sample.id2".genotypes.txt
EOF
# use the data from the array
for f in "${ary[#]}"; do
printf '%s\n' "$f"
done
It will make your life a bit easier if your data grows, and you can then very easily transfer it to another file. Of course, if it's only for a one-time use (e.g., you made an error when naming your files and you only want to rename them), then learn how to have Bash properly parse the quotes as shown in the other answers (escaping them or using single quotes).
I have a bash script like this:
myfiles=("file\ with\ spaces.csv")
for file_name in "${myfiles[#]}"
do
echo "removing first line of file $file_name"
echo "first line is `head -1 $file_name`"
echo "\n"
done
but it does not recognize the spaces for some reason, even though I enclosed it in double quotes "":
head: cannot open ‘file\\’ for reading: No such file or directory
How do I fix this?
You need double quotes inside the backticks. The outer set isn't sufficient.
echo "first line is `head -1 "$file_name"`"
Also, do not put backslashes in the file name, since it's already quoted. Quotes or backslashes, but not both.
myfiles=("file with spaces.csv")
myfiles=(file\ with\ spaces.csv)
To expand on #JohnKugelman's answer:
Quoting takes a bit of getting used to in Bash. As a simple rule use single quotes for static strings with no special characters, double quotes for strings with variables, and $'' quoting for strings with special characters.
There's a separate quoting context inside every command substitution.
$() is a clearer way to establish a command substitution, because it can be nested much easier.
Consequently you'd typically write myfiles=('file with spaces.csv') and echo "first line is $(head -1 "$file_name")".
I want to issue this command from the bash script
sed -e $beginning,$s/pattern/$variable/ file
but any possible combination of quotes gives me an error, only one that works:
sed -e "$beginning,$"'s/pattern/$variable/' file
also not good, because it do not dereferences the variable.
Does my approach can be implemented with sed?
Feel free to switch the quotes up. The shell can keep things straight.
sed -e "$beginning"',$s/pattern/'"$variable"'/' file
You can try this:
$ sed -e "$beginning,$ s/pattern/$variable/" file
Example
file.txt:
one
two
three
Try:
$ beginning=1
$ variable=ONE
$ sed -e "$beginning,$ s/one/$variable/" file.txt
Output:
ONE
two
three
There are two types of quotes:
Single quotes preserve their contents (> is the prompt):
> var=blah
> echo '$var'
$var
Double quotes allow for parameter expansion:
> var=blah
> echo "$var"
blah
And two types of $ sign:
One to tell the shell that what follows is the name of a parameter to be expanded
One that stands for "last line" in sed.
You have to combine these so
The shell doesn't think sed's $ has anything to do with a parameter
The shell parameters still get expanded (can't be within single quotes)
The whole sed command is quoted.
One possibility would be
sed "$beginning,\$s/pattern/$variable/" file
The whole command is in double quotes, i.e., parameters get expanded ($beginning and $variable). To make sure the shell doesn't try to expand $s, which doesn't exist, the "end of line" $ is escaped so the shell doesn't try anything funny.
Other options are
Double quoting everything but adding a space between $ and s (see Ren's answer)
Mixing quoting types as needed (see Ignacio's answer)
Methods that don't work
sed '$beginning,$s/pattern/$variable/' file
Everything in single quotes: the shell parameters are not expanded (doesn't follow rule 2 above). $beginning is not a valid address, and pattern would be literally replaced by $variable.
sed "$beginning,$s/pattern/$variable/" file
Everything in double qoutes: the parameters are expanded, including $s, which isn't supposed to (doesn't follow rule 1 above).
the following form worked for me from within script
sed $beg,$ -e s/pattern/$variable/ file
the same form will also work if executed from the shell
I am trying to write a script which will use echo and write/append to a file.
But I have " " in syntax already in strings .. say ..
echo "I am "Finding" difficult to write this to file" > file.txt
echo "I can "write" without double quotes" >> file.txt
Can anyone please help to understand this, really appreciated.
BR,
SM
If you want to have quotes, then you must escape them using the backslash character.
echo "I am \"Finding\" difficult to write this to file" > file.txt echo
echo "I can \"write\" without double quotes" >> file.txt
The same holds true if you i.e. also want to write the \ itself, as it may cause side effects. So you have to use \\
Another option would be to use The `'' instead of quotes.
echo 'I am "Finding" difficult to write this to file' > file.txt echo
echo 'I can "write" without double quotes' >> file.txt
However in this case variable substition doesn't work, so if you want to use variables you have to put them outside.
echo "This is a test to write $PATH in my file" >> file.txt
echo 'This is a test to write '"$PATH"' in my file' >> file.txt
If you have special characters, you can escape them with a backslash to use them as needed:
echo "I am \"Finding\" difficult to write this to file" > file.txt
echo "I can \"write\" without double quotes" >> file.txt
However, you can also use the shell's "EOF" feature with the tee command, which is really nice for writing all sorts of things:
tee -a file.txt <<EOF
I am "Finding" difficult to write this to file
I can "write" without double quotes
EOF
That will write virtually ANY content you want directly to that file, and escape any special characters until you get to the EOF.
*Edited to add the append switch, to prevent overwriting the file:
-a