8

System

Linux hosek 4.15.0-48-generic #51-Ubuntu SMP Wed Apr 3 08:28:49 UTC 2019 x86_64 x86_64 x86_64 GNU/Linux

Issue

I need to get output as commands, in a bash script, for storing variables.

Example

sed -n '/# Main configuration./,/# Websites./p' webcheck-$category.cfg | sed '1,1d' | sed '$ d'

This command returns these lines:

email_sender='some@email.com'
email_recipients='another@email.com'

How can I read/run these output/lines as commands in script? Is storing this output to the file and then read it by source command only way?

I tried | source at the end of the command, but it reads only from files.

I tried echo at the beginning, but that had no effect.

Thanks.

15

As pLumo showed you, you can indeed source them. However, I would recommend against this. If you have something like this:

source <(sed -n '/# Main configuration./,/# Websites./p' webcheck-$category.cfg | sed '1,1d' | sed '$ d')

echo "$email_sender"

Then, a year later when you come back and look at this script, you will have no idea where this email_sender variable is coming from. I suggest you instead change the command and use one that returns only the variable's value and not its name. That way, you can easily keep track of where each variable comes from:

email_sender=$(grep -oP 'email_sender=\K.*' webcheck-$category.cfg)
email_recipients=$(grep -oP 'email_recipients=\K.*' webcheck-$category.cfg)
3
  • I agree this is better ;-) At least for scripts you intend to use later.
    – pLumo
    Sep 12 '19 at 11:55
  • Thanks to both! Nice and simple. ;)
    – genderbee
    Sep 12 '19 at 12:12
  • For two this is OK, for more I use for loops with an indirection: for var in email_sender email_recipient email_subject email_attachement etc ; do printf -v "${var}" '%s' "$(grep -oP $var'=\K.*' webcheck-$category.cfg)"; done However this fails the "simple" criteria.
    – Law29
    Sep 13 '19 at 21:14
3

You can use process substitution:

source <(sed -n '/# Main configuration./,/# Websites./p' webcheck-$category.cfg | sed '1,1d' | sed '$ d')
0
#!/bin/bash

declare -A data
while IFS='=' read -r key value; do
    data[$key]=${value//\'/}
done < <(grep -E '^([^#].+=.*)' webcheck-$category.cfg)

or

done < <(sed -n '/# Main configuration./,/# Websites./{//!p}' webcheck-$category.cfg)
# associative array.
echo ${data[email_sender]}
echo ${data[email_recipients]}

Output:

some@email.com another@email.com

-1

bash read builtin handles things like this nicely.

read -d '' -r email_sender email_recipients < <(
  grep -oP 'email_sender=\K.*' webcheck-$category.cfg; 
  grep -oP 'email_recipients=\K.*' webcheck-$category.cfg
)

read reads lines from stdin into variables. -d '' turns off whitespace splitting, except for newlines. -r disables \ escapes.

cmdA < <(cmdB) works similarly to cmdB | cmdA, except in the former cmdA is run in ~this~ shell, instead of a subshell, which is required for read to work as expected.

2
  • 1
    Can you some explanation on the different parts of the line? Sep 13 '19 at 10:38
  • This is true, but how is it relevant to the question asked where the objective is to read from a file with var=value?
    – terdon
    Sep 14 '19 at 12:27

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.