how to echo without being executed - bash

I am trying to add echo statements in /etc/profile but they execute.
Example: This is what I wrote
echo CURRENTYEAR="`/bin/date +%y`" >> /etc/profile
echo CURRENTWEEK="`/bin/date +%V` " >> /etc/profile
echo VERSION="$CURRENTYEAR"."$CURRENTWEEK" >> /etc/profile
echo export VERSION >> /etc/profile
echo export SVN_HOME="https://example.com/svn/road" >> /etc/profile
echo SVN_BRANCH="$SVN_HOME/branches/qa_weekly/$VERSION" >> /etc/profile
echo export SVN_TAG="https://example.cpm/svn/road/tags" >> /etc/profile
echo export SVN_TRUNK="https://example.com/svn/empire/trunk" >> /etc/profile
export PATH=$PATH:/road >> /etc/profile
export SVN_BRANCH
Result: what I get
CURRENTYEAR=15
CURRENTWEEK=33
VERSION=.
export VERSION
export SVN_HOME=https://example.com/svn/road
SVN_BRANCH=/branches/qa_weekly/
export SVN_TAG=https://example.com/svn/road/tags
export SVN_TRUNK=https://example.com/svn/road/trunk
I want it as below in /etc/profile
CURRENTYEAR=`/bin/date +%y`
CURRENTWEEK=`/bin/date +%V`
VERSION=$CURRENTYEAR"."$CURRENTWEEK
export VERSION
SVN_BRANCH=$SVN_HOME/branches/qa_weekly/$VERSION
SVN_TAG=$SVN_HOME/tags
SVN_TRUNK=$SVN_HOME/trunk
Thanks in Advance.

Put your strings in single quotes:
echo 'CURRENTYEAR="`/bin/date +%y`"' >> /etc/profile
#....^.............................^
http://www.gnu.org/software/bash/manual/bashref.html#Single-Quotes
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.

Rather than multiple echo statements, use cat with a quoted here document:
cat >> /etc/profile <<'EOF'
CURRENTYEAR=`/bin/date +%y`
CURRENTWEEK=`/bin/date +%V`
VERSION="$CURRENTYEAR.$CURRENTWEEK"
export VERSION
export SVN_HOME="https://example.com/svn/road"
SVN_BRANCH="$SVN_HOME/branches/qa_weekly/$VERSION"
export SVN_TAG="https://example.cpm/svn/road/tags"
export SVN_TRUNK="https://example.com/svn/empire/trunk"
export PATH=$PATH:/road
export SVN_BRANCH
EOF
Quoting EOF in the first line prevents any substitutions from occurring in the body of the here document.

Related

Unbound variable

this is a bug I have found nothing about after a relentless search
I'm trying to run a bootstrap file in an EC2 instance, part of an EMR cluster v6.4.0. As the bootstrap action takes longer than 5 minutes, we execute it as a subprocess of the form
#!/bin/bash
var="var"
cat << EOF > ~/bootstrap.sh
intra="intra"
echo $var
echo $intra
EOF
/bin/bash ~/bootstrap.sh
exit 0
But the var "intra" is never set, and the bootstrap action returns the error line n: intra: unbound variable
If you execute that script the "intra" var is not printed.
Why can't I assign variables in a subprocess? Thank you!
When using that type of heredoc (<<WORD), you must escape literal $ characters using \$. Same goes for the backtick character (`):
#!/bin/bash
var="var"
cat << EOF > ~/bootstrap.sh
intra="intra"
echo $var
echo \$intra
EOF
/bin/bash ~/bootstrap.sh
exit 0
Another way of generating an equivalent bootstrap script is to use the literal heredoc form <<'WORD':
#!/bin/bash
var="var"
# This line will be inserted as-is without variable and subshell expansion:
cat << 'EOF1' > ~/bootstrap.sh
intra="intra"
EOF1
# We will allow this ONE line to expand.
cat << EOF2 >> ~/bootstrap.sh
echo $var
EOF2
# Back to literal insertions, no escaping necessary.
cat << 'EOF3' >> ~/bootstrap.sh
echo $intra
EOF3
/bin/bash ~/bootstrap.sh
exit 0
Inspecting the contents of ~/bootstrap.sh is a good place to start debugging.

Double expansion of shell variable

I have a table which contains an env variable and I need to fetch the variable's value and export for another java utility from within the shell script:
command="SELECT param_value FROM tableX WHERE param_name='ABCD';"
#This param_value is ${PATHX} and PATHX is /home/users/pathx
PARAM_VALUE=`sqlplus -s $CONN_STRING <<- END
SET head off;
set feedback off;
${command}
exit;
END`
echo ${PARAM_VALUE} | grep -q "ERROR"
if [ $? -eq 0 ]
then
echo "Failed in fetching param_value "
exit 1
else
#Trimming the value fetched from DB
PARAM_VALUE=`echo "${PARAM_VALUE}" | tr -d " " | tr -d "\n"`
echo "Value fetched from DB=${PARAM_VALUE}"
#This prints ${PATHX}
export PATH_VALUE="${PARAM_VALUE}"
#This is exporting PATH_VALUE as ${PATHX} instead of /home/users/pathx - WHICH IS WHERE I NEED HELP
#If I put directly export PATH_VALUE="${PATHX}", it exports the value correctly as /home/users/pathx
fi
After searching for options, I have tried various options like below but failed:
export PATH_VALUE="${PARAM_VALUE}"
export PATH_VALUE=`eval echo "\$${PARAM_VALUE}"`
export PATH_VALUE=$(eval \$$PARAM_VALUE)
export PATH_VALUE=${$PARAM_VALUE}
export PATH_VALUE=${!PARAM_VALUE}
export PATH_VALUE=`echo ${PARAM_VALUE}`
export PATH_VALUE=`expr ${PARAM_VALUE}`
Please suggest what can be done in this case to export the actual expanded value - /home/users/pathx.
For it to work the way you expect, the sqlplus query response should be PATHX instead of ${PATHX}. One way to fix it is to replace
PARAM_VALUE=`echo "${PARAM_VALUE}" | tr -d " " | tr -d "\n"`
with
PARAM_VALUE=`echo "${PARAM_VALUE}" | tr -dc '[:alnum:]\n\r'`
yes the query response is ${PATHX} and this is an environment variable which I need to expand.
You could use eval, but eval is evil, if the value is exported, do a safe envsubst:
PARAM_VALUE=$(envsubst <<<"$PARAM_VALUE")

How to echo literal output in bash

I would like to "copy-paste" the following lines in a script into my bashrc:
# VIM,TMUX stuff
VIM="$(which vim)"
For example:
echo "# VIM,TMUX stuff" >> ~/.bash_profile
echo 'VIM="$(which vim)"' >> ~/.bash_profile
However, it seems to 'escape' some of the items. How would I do the equivalent of a literal 'copy-paste' as I'm trying to do above?
Use heredoc in bash:
cat <<-'EOF' > ~/.bash_profile
# VIM,TMUX stuff
VIM="$(which vim)"
EOF

Generate multiline file with Make

I want to create a multiline file with Make, having exact content:
#!/bin/bash
if [ "$JAVA_HOME" = "" ]; then echo "Please set JAVA_HOME"; exit 1; fi
export CONFIG_VARS=$( cat <<EOF
-Dmapred.job.tracker=$JT
EOF
)
${HADOOP_HOME}/bin/hadoop $1 $HADOOP_CONFIG_VARS ${*:2} 2>&1 | grep -v SLF4J
How can I tell make to output a file with this exact content somewhere?
I tried this:
define SCRIPT_CONTENT
#!/bin/bash
if [ "$JAVA_HOME" = "" ]; then echo "Please set JAVA_HOME"; exit 1; fi
export CONFIG_VARS=$( cat <<EOF
-Dmapred.job.tracker=$JT
EOF
)
${HADOOP_HOME}/bin/hadoop $1 $HADOOP_CONFIG_VARS ${*:2} 2>&1 | grep -v SLF4J
endef
export SCRIPT_CONTENT
bin/script:
#echo "$$SCRIPT_CONTENT" > bin/script
This paricular solution 1) wipes $ and first char after $-es and 2) is ugly because the definition should happen outside of the particular target where it's needed :(
I also tried this:
bin/script:
#echo '
#!/bin/bash
if [ "$JAVA_HOME" = "" ]; then echo "Please set JAVA_HOME"; exit 1; fi
export CONFIG_VARS=$( cat <<EOF
-Dmapred.job.tracker=$JT
EOF
)
${HADOOP_HOME}/bin/hadoop $1 $HADOOP_CONFIG_VARS ${*:2} 2>&1 | grep -v SLF4J
' > bin/script
This returns error when in make, works outside of make...
Any suggestion is very welcome!
Make wants any $ characters that should be reproduced literally to be escaped by inserting another $ in front of them.
More broadly, though, it seems like you're trying to use Make as a shell-script replacement. The more idomatic way to do this would be to put that content in a source file that you can copy to the destination, or to put it in a script that will write it into a specified destination. The Makefile then just has to invoke the copy command or the script.
With the help from this magnificent answer, I cooked up the following.
# From https://stackoverflow.com/a/8316519/874188
define \n
endef
define SCRIPT_CONTENT
#!/bin/bash
if [ "$$JAVA_HOME" = "" ]; then echo "Please set JAVA_HOME"; exit 1; fi
export CONFIG_VARS=$$( cat <<EOF
-Dmapred.job.tracker=$$JT
EOF
)
$${HADOOP_HOME}/bin/hadoop $$1 $$HADOOP_CONFIG_VARS $${*:2} 2>&1 | grep -v SLF4J
endef
bin/script:
echo '$(subst $(\n),\n,$(SCRIPT_CONTENT))' >$#
When testing, I found that I needed to have a semicolon at the end of the echo line when it didn't have any redirection. I can speculate that there is a built-in echo which gets invoked when there are no shell metacharacters in the command line?
Also, notice that the definition cannot contain any single quotes, and that all dollar signs have to be doubled. Maybe one or the other of these restrictions could be removed; I was unsuccessful, but then I didn't spend too much time or effort.
You cannot do this in make. Beyond what Novelocrat says regarding $, there's the fact that make is line-oriented and does not have any ability to generate a command that contains a newline character. All newlines that appear unescaped (without a backslash before them) are parsed by make as ending that recipe line, and each recipe line is sent to a different invocation of the shell. If you want the entire command to be sent as a single string to the same shell, then you must escape the newlines.
However, make will remove all backslash/newline pairs before it runs the command.
The only possible way to do this completely within make is to generate the file one line at a time, like this:
bin/script:
#echo '#!/bin/bash' > $#
#echo 'if [ "$$JAVA_HOME" = "" ]; then echo "Please set JAVA_HOME"; exit 1; fi' >> $#
#echo 'export CONFIG_VARS=$$( cat <<EOF' >> $#
#echo ' -Dmapred.job.tracker=$$JT' >> $#
#echo 'EOF' >> $#
#echo ')' >> $#
#echo '$${HADOOP_HOME}/bin/hadoop $$1 $$HADOOP_CONFIG_VARS $${*:2} 2>&1 | grep -v SLF4J' >> $#
As Novelocrat says, the typical way this is done is to have the script file as a separate file and copy it where you want it, rather than generating it.

Exporting environment variable in bash script - it doesnt work

I wrote a little bash script to export environment variable:
#!/bin/bash
echo "Pass a path:"
read path
echo $path
defaultPath = /home/katie/Desktop
if [ -n "$path" ]; then
echo "Path is empty! Exporting default path ..."
export my_var=$defaultPath
else
export my_var=$path
fi
but I got error:
defaultPath: command not found
How to fix it?
WORKNG VERSION:
#!/bin/bash
echo "Pass a path:"
read path
echo $path
defaultPath=/home/user/Desktop
if [ -n "$path" ]; then
export my_var=$path
else
echo "Path is empty! Exporting default path ..."
export my_var=$defaultPath
fi
No whitespace is allowed surrounding the = in a variable assignment:
defaultPath=/home/katie/Desktop
With spaces, the line is interpreted as a simple command that attempts to execute the command defaultPath with two arguments, = and /home/katie/Desktop.

Resources