-2

I have code like the following:

read var9
echo 'option domain-name' '"'$var9'"'';' >>dhcpd.conf

I want the output to look like:

option domain-name "sr.lan";

but the syntax-highlighting in my editor shows the $var1 highlighted as if it were literal text, not a variable reference, as shown in the below image.

What's wrong with this?

Here is a picture of my script: My script

Charles Duffy
  • 280,126
  • 43
  • 390
  • 441
Manu
  • 1
  • 2
  • See [Why not upload images of code when asking a question?](https://meta.stackoverflow.com/a/285557/14122) -- moreover, something behind a link does not count as being "in the question itself" for purposes of compliance with [mcve] rules. Note that we a specific error to be included in the question itself, as well as (only) the shortest code that can be used to test whether the error is fixed. – Charles Duffy Feb 19 '19 at 20:13
  • Please add code, not pictures. And it's unclear to me what you're actually asking. – tink Feb 19 '19 at 20:14
  • I posted in a picture for show that it was as yellow like text instead in red of a variable – Manu Feb 19 '19 at 20:16
  • [Edit] your question and add the code **as text**, even if it's in addition to the image rather than instead of it. We can't copy-and-paste to reproduce an issue, or run it through our own syntax-checking tools, or test a proposed fix, if all you give us is a screenshot. – Charles Duffy Feb 19 '19 at 20:32
  • 1
    BTW, one question whose answers are also usable here is [Bash Templating: How to build configuration files from templates with Bash?](https://stackoverflow.com/questions/2914220/bash-templating-how-to-build-configuration-files-from-templates-with-bash) – Charles Duffy Feb 19 '19 at 20:46
  • 1
    You should get into the habit of using more descriptive variable names. `$var9` has no meaning, except that it's the 9th variable. `$opt_domain_name` is very informative. – glenn jackman Feb 19 '19 at 21:00
  • `echo 'option domain-name' '"'$var9'"'';'` emits `option domain-name "sr.lan";`. That's what you *want*, isn't it? So this code is verbose, slow and ugly, but I don't see how it's wrong. (It would be much less slow if you didn't have the `>>dhcpd.conf` on every single line; you can put `exec >dhcpd.conf` only once at the beginning of your script, and that will redirect *every* `echo` and other write to stdout there). – Charles Duffy Feb 19 '19 at 21:07
  • 1
    The yellow `"$var9"` isn't indicative of a bug, the red `$var1` is. You should **never** expand variables unquoted: That is, safely/correctly-written bash code would refer to `"$var1"`, not `$var1`. – Charles Duffy Feb 19 '19 at 21:10

2 Answers2

1

You can try one of these solutions:

  • echo 'option domain-name "'"$var9"'";' >> dhcpd.conf
  • echo "option domain-name \"$var9\";" >> dhcpd.conf
  • printf 'option domain-name "%s";' "$var9" >> dhcpd.conf

However, I'd rather recommend to use a pre-defined template (separated file) and replace the relevant variable occurrences with sed, perl or maybe mustache, rather than doing something like echo ... $var9 ... >> dhcpd.conf.

For example, using the Bash implementation of mustache, mo:

# Create demo file
cat > demo.mo <<EOF
option routers {{var1}};
option domain-name "{{var9}}";
EOF

# Install mustache for Bash
curl -fsSL https://git.io/get-mo -o mo
# inspect the bash script "mo" so downloaded,
# then add the executable flag
chmod +x mo
# and put "mo" in your PATH, e.g.: sudo mv mo /usr/local/bin/

# Use mustache
var1="Démo_var_1" var9="Démo var 9" mo demo.mo > demo.txt

then you obtain:

demo.txt

option routers Démo_var_1;
option domain-name "Démo var 9";

There is also a Python version in PyPI: pystache.

But of course, there are many open-source programs that provide a similar feature.

For example, as mentioned by @CharlesDuffy, the envsubst program could also be used, relying merely on gettext, see e.g. these references:

ErikMD
  • 13,377
  • 3
  • 35
  • 71
  • Simpler than `mo` would be to use `envsubst`, which has the advantage of already being installed everywhere with GNU gettext. See also [TemplateFiles](https://mywiki.wooledge.org/TemplateFiles) on the Wooledge wiki. – Charles Duffy Feb 19 '19 at 20:38
  • @CharlesDuffy indeed, I had chosen the bash version `mo` for simplicity but it is unfortunately the `mo` script is not directly available in the usual Linux distributions: there is only some package for Common Lisp, Ruby, Haskell, Java and JavaScript [in Ubuntu](https://packages.debian.org/search?keywords=mustache)… or it is also available [in PyPI: package pystache](https://pypi.org/project/pystache/). I've added a comment suggesting to inspect the script beforehand but I agree that it's always better to rely on package managers… Would you advise to replace `mo` with `pystache`? – ErikMD Feb 19 '19 at 20:55
  • @CharlesDuffy otherwise, feel free to edit my answer or to post another answer with extra examples if it looks sensible to you. – ErikMD Feb 19 '19 at 20:57
  • or just `echo "option domain-name \"$var9\";" >> ...` – ilkkachu Feb 19 '19 at 21:30
  • @ilkkachu indeed, that allows one to save 2 characters :) I updated my answer; but relying on templates would be a much cleaner solution IMHO. – ErikMD Feb 19 '19 at 21:34
  • @ErikMD, oh, I have nothing against the template idea. I just find mixed single and double quotes hard to read, I didn't check the character count :) – ilkkachu Feb 19 '19 at 21:36
-1

For what it's worth, if your editor shows the $var9 part as if it were quoted, then it seems it interprets the quotes wrong. Your line has four distinct quoted strings, marked below. Note that the variable $var9 is not quoted. However, you should double-quote variables to avoid issues with word splitting and accidental expansion of filename wildcards.

echo 'option domain-name' '"'$var9'"'';' >>dhcpd.conf
     11111111111111111111-222-----333444

ErikMD's answer has the properly quoted and more readable alternatives.

ilkkachu
  • 6,221
  • 16
  • 30