Skip to main content
replaced http://unix.stackexchange.com/ with https://unix.stackexchange.com/
Source Link

While you can transform this file to be a shell snippet, it's tricky. You need to make sure that all shell special characters are properly quoted.

The easiest way to do that is to put single quotes around the valueput single quotes around the value and replace single quotes inside the value by '\''. You can then put the result into a temporary file and source that file.

script=$(mktemp) sed <"config-file" >"$script" \ -e '/^[A-Z_a-z][A-Z_a-z]*=/ !d' \ -e s/\'/\'\\\\\'\'/g \ -e s/=/=\'/ -e s/\$/\'/ 

I recommend doing the parsing directly in the shell instead. The complexity of the code is about the same, but there are two major benefits: you avoid the need for a temporary file, and the risk that you accidentally got the quoting wrong and end up executing a part of a line as a shell snippet (something like dangerous='$(run me)'). You also get a better chance at validating potential errors.

while IFS= read -r line; do line=${line%%#*} # strip comment (if any) case $line in *=*) var=${line%%=*} case $var in *[!A-Z_a-z]*) echo "Warning: invalid variable name $var ignored" >&2 continue;; esac if eval '[ -n "${'$var'+1}" ]'; then echo "Warning: variable $var already set, redefinition ignored" >&2 continue fi line=${line#*=} eval $var='"$line"' esac done <"config-file" 

While you can transform this file to be a shell snippet, it's tricky. You need to make sure that all shell special characters are properly quoted.

The easiest way to do that is to put single quotes around the value and replace single quotes inside the value by '\''. You can then put the result into a temporary file and source that file.

script=$(mktemp) sed <"config-file" >"$script" \ -e '/^[A-Z_a-z][A-Z_a-z]*=/ !d' \ -e s/\'/\'\\\\\'\'/g \ -e s/=/=\'/ -e s/\$/\'/ 

I recommend doing the parsing directly in the shell instead. The complexity of the code is about the same, but there are two major benefits: you avoid the need for a temporary file, and the risk that you accidentally got the quoting wrong and end up executing a part of a line as a shell snippet (something like dangerous='$(run me)'). You also get a better chance at validating potential errors.

while IFS= read -r line; do line=${line%%#*} # strip comment (if any) case $line in *=*) var=${line%%=*} case $var in *[!A-Z_a-z]*) echo "Warning: invalid variable name $var ignored" >&2 continue;; esac if eval '[ -n "${'$var'+1}" ]'; then echo "Warning: variable $var already set, redefinition ignored" >&2 continue fi line=${line#*=} eval $var='"$line"' esac done <"config-file" 

While you can transform this file to be a shell snippet, it's tricky. You need to make sure that all shell special characters are properly quoted.

The easiest way to do that is to put single quotes around the value and replace single quotes inside the value by '\''. You can then put the result into a temporary file and source that file.

script=$(mktemp) sed <"config-file" >"$script" \ -e '/^[A-Z_a-z][A-Z_a-z]*=/ !d' \ -e s/\'/\'\\\\\'\'/g \ -e s/=/=\'/ -e s/\$/\'/ 

I recommend doing the parsing directly in the shell instead. The complexity of the code is about the same, but there are two major benefits: you avoid the need for a temporary file, and the risk that you accidentally got the quoting wrong and end up executing a part of a line as a shell snippet (something like dangerous='$(run me)'). You also get a better chance at validating potential errors.

while IFS= read -r line; do line=${line%%#*} # strip comment (if any) case $line in *=*) var=${line%%=*} case $var in *[!A-Z_a-z]*) echo "Warning: invalid variable name $var ignored" >&2 continue;; esac if eval '[ -n "${'$var'+1}" ]'; then echo "Warning: variable $var already set, redefinition ignored" >&2 continue fi line=${line#*=} eval $var='"$line"' esac done <"config-file" 
detect the case when $var is already defined
Source Link
Gilles 'SO- stop being evil'
  • 866.5k
  • 205
  • 1.8k
  • 2.3k

While you can transform this file to be a shell snippet, it's tricky. You need to make sure that all shell special characters are properly quoted.

The easiest way to do that is to put single quotes around the value and replace single quotes inside the value by '\''. You can then put the result into a temporary file and source that file.

script=$(mktemp) sed <"config-file" >"$script" \ -e '/^[A-Z_a-z][A-Z_a-z]*=/ !d' \ -e s/\'/\'\\\\\'\'/g \ -e s/=/=\'/ -e s/\$/\'/ 

I recommend doing the parsing directly in the shell instead. The complexity of the code is about the same, but there are two major benefits: you avoid the need for a temporary file, and the risk that you accidentally got the quoting wrong and end up executing a part of a line as a shell snippet (something like dangerous='$(run me)'). You also get a better chance at validating potential errors.

while IFS= read -r line; do line=${line%%#*} # strip comment (if any) case $line in *=*) var=${line%%=*} case $var in *[!A-Z_a-z]*|line|varz]*) echo "Warning: invalid variable name $var ignored" >&2 continue;; esac if eval '[ -n "${'$var'+1}" ]'; then echo "Warning: variable $var already set, redefinition ignored" >&2 continue fi line=${line#*=} eval $var='"$line"' esac done <"config-file" 

While you can transform this file to be a shell snippet, it's tricky. You need to make sure that all shell special characters are properly quoted.

The easiest way to do that is to put single quotes around the value and replace single quotes inside the value by '\''. You can then put the result into a temporary file and source that file.

script=$(mktemp) sed <"config-file" >"$script" \ -e '/^[A-Z_a-z][A-Z_a-z]*=/ !d' \ -e s/\'/\'\\\\\'\'/g \ -e s/=/=\'/ -e s/\$/\'/ 

I recommend doing the parsing directly in the shell instead. The complexity of the code is about the same, but there are two major benefits: you avoid the need for a temporary file, and the risk that you accidentally got the quoting wrong and end up executing a part of a line as a shell snippet (something like dangerous='$(run me)'). You also get a better chance at validating potential errors.

while IFS= read -r line; do line=${line%%#*} # strip comment (if any) case $line in *=*) var=${line%%=*} case $var in *[!A-Z_a-z]*|line|var) echo "Warning: invalid variable name $var ignored" >&2 continue;; esac line=${line#*=} eval $var='"$line"' esac done <"config-file" 

While you can transform this file to be a shell snippet, it's tricky. You need to make sure that all shell special characters are properly quoted.

The easiest way to do that is to put single quotes around the value and replace single quotes inside the value by '\''. You can then put the result into a temporary file and source that file.

script=$(mktemp) sed <"config-file" >"$script" \ -e '/^[A-Z_a-z][A-Z_a-z]*=/ !d' \ -e s/\'/\'\\\\\'\'/g \ -e s/=/=\'/ -e s/\$/\'/ 

I recommend doing the parsing directly in the shell instead. The complexity of the code is about the same, but there are two major benefits: you avoid the need for a temporary file, and the risk that you accidentally got the quoting wrong and end up executing a part of a line as a shell snippet (something like dangerous='$(run me)'). You also get a better chance at validating potential errors.

while IFS= read -r line; do line=${line%%#*} # strip comment (if any) case $line in *=*) var=${line%%=*} case $var in *[!A-Z_a-z]*) echo "Warning: invalid variable name $var ignored" >&2 continue;; esac if eval '[ -n "${'$var'+1}" ]'; then echo "Warning: variable $var already set, redefinition ignored" >&2 continue fi line=${line#*=} eval $var='"$line"' esac done <"config-file" 
Source Link
Gilles 'SO- stop being evil'
  • 866.5k
  • 205
  • 1.8k
  • 2.3k

While you can transform this file to be a shell snippet, it's tricky. You need to make sure that all shell special characters are properly quoted.

The easiest way to do that is to put single quotes around the value and replace single quotes inside the value by '\''. You can then put the result into a temporary file and source that file.

script=$(mktemp) sed <"config-file" >"$script" \ -e '/^[A-Z_a-z][A-Z_a-z]*=/ !d' \ -e s/\'/\'\\\\\'\'/g \ -e s/=/=\'/ -e s/\$/\'/ 

I recommend doing the parsing directly in the shell instead. The complexity of the code is about the same, but there are two major benefits: you avoid the need for a temporary file, and the risk that you accidentally got the quoting wrong and end up executing a part of a line as a shell snippet (something like dangerous='$(run me)'). You also get a better chance at validating potential errors.

while IFS= read -r line; do line=${line%%#*} # strip comment (if any) case $line in *=*) var=${line%%=*} case $var in *[!A-Z_a-z]*|line|var) echo "Warning: invalid variable name $var ignored" >&2 continue;; esac line=${line#*=} eval $var='"$line"' esac done <"config-file"