Unable to add escape sequences dynamically for 'PS1' - bash

Say I want to include an escape sequence dynamically:
if [ -n $something ]; then
user="\u"
else
user="admin"
fi
PS1='$user#\h$ '
The problem is, instead of filling in the user name, my prompt looks like this:
\u#ubuntu-1$
Even if I escape the backslash (user="\\u") it still does not print out the user name. How do I get the prompt to look like this:
andreas#ubuntu-1$

Use double quotes when you are trying to interpolate variables and want them to expand.
You also have another option, instead of dealing with \u and complications with when the interpretation of it happens.
if [ -n $something ]; then
user=`whoami`
else
user="admin"
fi
PS1="$user#\h$ "

Related

How to put single quotes in bash

ABcD!987zyz12388
I'd like to put single quotes around it to handle special character/s. This password is fetched and saved to a variable.
$mypass=`fetchpwd $sourceserver $loginacct`;
$mypass="'$mypass'";
print "My password is: $mypass\n";
The return looks like this
My Password is 'ABcD!987zyz12388
'
The quotes don't belong in the variable itself; they should be added by the printf statement that displays the value.
mypass=$(fetchpwd "$sourceserver" "$logginacct")
printf "My password is: '%s'\n" "$mypass"
If fetchpwd is adding an extra newline you can remove newlines using
mypass=$(fetchpwd "$sourceserver" "$logginacct" | tr -d '\n')

How to concatenate string variables that contain space? [duplicate]

How can I escape double quotes inside a double string in Bash?
For example, in my shell script
#!/bin/bash
dbload="load data local infile \"'gfpoint.csv'\" into table $dbtable FIELDS TERMINATED BY ',' ENCLOSED BY '\"' LINES TERMINATED BY \"'\n'\" IGNORE 1 LINES"
I can't get the ENCLOSED BY '\"' with double quote to escape correctly. I can't use single quotes for my variable, because I want to use variable $dbtable.
Use a backslash:
echo "\"" # Prints one " character.
A simple example of escaping quotes in the shell:
$ echo 'abc'\''abc'
abc'abc
$ echo "abc"\""abc"
abc"abc
It's done by finishing an already-opened one ('), placing the escaped one (\'), and then opening another one (').
Alternatively:
$ echo 'abc'"'"'abc'
abc'abc
$ echo "abc"'"'"abc"
abc"abc
It's done by finishing already opened one ('), placing a quote in another quote ("'"), and then opening another one (').
More examples: Escaping single-quotes within single-quoted strings
Keep in mind that you can avoid escaping by using ASCII codes of the characters you need to echo.
Example:
echo -e "This is \x22\x27\x22\x27\x22text\x22\x27\x22\x27\x22"
This is "'"'"text"'"'"
\x22 is the ASCII code (in hex) for double quotes and \x27 for single quotes. Similarly you can echo any character.
I suppose if we try to echo the above string with backslashes, we will need a messy two rows backslashed echo... :)
For variable assignment this is the equivalent:
a=$'This is \x22text\x22'
echo "$a"
# Output:
This is "text"
If the variable is already set by another program, you can still apply double/single quotes with sed or similar tools.
Example:
b="Just another text here"
echo "$b"
Just another text here
sed 's/text/"'\0'"/' <<<"$b" #\0 is a special sed operator
Just another "0" here #this is not what i wanted to be
sed 's/text/\x22\x27\0\x27\x22/' <<<"$b"
Just another "'text'" here #now we are talking. You would normally need a dozen of backslashes to achieve the same result in the normal way.
Bash allows you to place strings adjacently, and they'll just end up being glued together.
So this:
echo "Hello"', world!'
produces
Hello, world!
The trick is to alternate between single and double-quoted strings as required. Unfortunately, it quickly gets very messy. For example:
echo "I like to use" '"double quotes"' "sometimes"
produces
I like to use "double quotes" sometimes
In your example, I would do it something like this:
dbtable=example
dbload='load data local infile "'"'gfpoint.csv'"'" into '"table $dbtable FIELDS TERMINATED BY ',' ENCLOSED BY '"'"'"' LINES "'TERMINATED BY "'"'\n'"'" IGNORE 1 LINES'
echo $dbload
which produces the following output:
load data local infile "'gfpoint.csv'" into table example FIELDS TERMINATED BY ',' ENCLOSED BY '"' LINES TERMINATED BY "'\n'" IGNORE 1 LINES
It's difficult to see what's going on here, but I can annotate it using Unicode quotes. The following won't work in Bash – it's just for illustration:
dbload=‘load data local infile "’“'gfpoint.csv'”‘" into ’“table $dbtable FIELDS TERMINATED BY ',' ENCLOSED BY '”‘"’“' LINES ”‘TERMINATED BY "’“'\n'”‘" IGNORE 1 LINES’
The quotes like “ ‘ ’ ” in the above will be interpreted by bash. The quotes like " ' will end up in the resulting variable.
If I give the same treatment to the earlier example, it looks like this:
echo “I like to use” ‘"double quotes"’ “sometimes”
Store the double quote character in a variable:
dqt='"'
echo "Double quotes ${dqt}X${dqt} inside a double quoted string"
Output:
Double quotes "X" inside a double quoted string
Check out printf...
#!/bin/bash
mystr="say \"hi\""
Without using printf
echo -e $mystr
Output: say "hi"
Using printf
echo -e $(printf '%q' $mystr)
Output: say \"hi\"
Make use of $"string".
In this example, it would be,
dbload=$"load data local infile \"'gfpoint.csv'\" into table $dbtable FIELDS TERMINATED BY ',' ENCLOSED BY '\"' LINES TERMINATED BY \"'\n'\" IGNORE 1 LINES"
Note (from the man page):
A double-quoted string preceded by a dollar sign ($"string") will cause the string to be translated according to the current locale. If the current locale is C or POSIX, the dollar sign is ignored. If the string is translated and replaced, the replacement is double-quoted.
For use with variables that might contain spaces in you Bash script, use triple quotes inside the main quote, e.g.:
[ "$(date -r """$touchfile""" +%Y%m%d)" -eq "$(date +%Y%m%d)" ]
Add "\" before double quote to escape it, instead of \
#! /bin/csh -f
set dbtable = balabala
set dbload = "load data local infile "\""'gfpoint.csv'"\"" into table $dbtable FIELDS TERMINATED BY ',' ENCLOSED BY '"\""' LINES TERMINATED BY "\""'\n'"\"" IGNORE 1 LINES"
echo $dbload
# load data local infile "'gfpoint.csv'" into table balabala FIELDS TERMINATED BY ',' ENCLOSED BY '"' LINES TERMINATED BY "''" IGNORE 1 LINES

How can I accept unquoted strings containing backslashes?

I want a command to convert from windows to unix filenames, simply to replace backslashes with frontslashes... but without quoting the argument with "" because that's a chore when copy-pasting.
It works in the other direction (u2w) with the input quoted and without, but not for w2u.
machine:~/glebbb> w2u "a\b\c"
a/b/c
machine:~/glebbb> w2u a\b\c
abc
How can I make it work? I tried every form of escaping, echo -E, printf etc, nothing seems to work!
function w2u {
if [ -z "$1" ] ; then
echo "w2u: must provide path to convert!"
return 1
else
printf "\n%s\n\n" "$1" | sed -e 's#\\#\/#g'
return 0
fi
}
If you're copy-pasting and the path is contained in the X clipboard, you can use xclip:
xclip -o | sed -e 's#\\#\/#g'
If you've got a ton of file paths to convert, you can process the whole file instead:
sed ... < file
will produce a new stream with the backslashes changed to slashes.
Otherwise I can't think of any way how to not-escape the parameters to w2u and yet have backslashes lose their meaning.

Adding quotes to a String in bash script

I am trying to add quotes to a string. Like this:
stackoverflow => 'stackoverflow'
And then append this string to another variable separated by a 'comma'. like:
${list} (before appending) => 'stackexchange',.....,'meta'
${list},'stackoverflow' => 'stackexchange',.....,'meta','stackoverflow'
I've tried to do this:
if [ -z "$partition_list" ]
then
partition_list="'"${partition}"'"
else
partition_list=${partition_list}",'"${partition}"'"
fi
Note: $partition is the variable that I am trying to add quotes to. And $partition_list is the list I am trying to append $partition to.
It didn't work. I get the strings like this: ''\''10099'\''
EDIT:
I am getting the value of partition through this statement:
partition=`echo $f | awk -F '=' '{print $2}'`
Is there a way we can add 'sed' to this statement and add the quotes to $partition?
Any help would be much appreciated.
Thank you.
What about just this?
partition_list="${partition_list:+$partition_list,}'$partition'"
The if construct is replaced with parameter expansion that includes the comma if $partition_list is not null (using :+), and the single quotes inside double quotes don't stop the variable from being expanded.
Plus ... always quote the variables you refer to. Your idea of foo=$bar",'"$baz"'" has the potential to be disastrous because the variables might be expanded through globbing.
So if you DID want to do this with the if, it would look more like:
if [ -z "$partition_list" ]; then
partition_list="'${partition}'"
else
partition_list="${partition_list},'${partition}'"
fi
How about:
//EDIT: updated for handling spaces.
list=('aa xx' 'bb')
res=()
for ix in ${!list[*]};do
res+=(\'${list[$ix]}\')
done
res+=("'stackoverflow'")
echo ${res[*]}

shell .bashrc not handling text wrapping

I found a good customization to my .bashrc for my prompt to show extra information and provide color highlighting. Here's what I have:
# ----- Define a few Colors
BLACK='\e[0;30m'
BLUE='\e[0;34m'
GREEN='\e[0;32m'
CYAN='\e[0;36m'
RED='\e[0;31m'
PURPLE='\e[0;35m'
BROWN='\e[0;33m'
LIGHTGRAY='\e[0;37m'
DARKGRAY='\e[1;30m'
LIGHTBLUE='\e[1;34m'
LIGHTGREEN='\e[1;32m'
LIGHTCYAN='\e[1;36m'
LIGHTRED='\e[1;31m'
LIGHTPURPLE='\e[1;35m'
YELLOW='\e[1;33m'
WHITE='\e[1;37m'
function __setprompt {
local SSH_IP=`echo $SSH_CLIENT | awk '{ print $1 }'`
local SSH2_IP=`echo $SSH2_CLIENT | awk '{ print $1 }'`
if [ $SSH2_IP ] || [ $SSH_IP ] ; then
local SSH_FLAG="#\h"
fi
PS1="$CYAN[\u$SSH_FLAG:$BROWN\w$CYAN]\\$ $NOCOLOR"
PS2="$CYAN>$NOCOLOR "
PS4='$CYAN+$NOCOLOR '
}
__setprompt
The issue I'm running into is that it doesn't handle wrapping text correctly (see below screenshot). Can anyone offer any advice on what the problem might be? It looks like it doesn't adjust at all what is typed in by the user.
what's the value of CYAN BROWN NOCOLOR vars ?
You most problably forgot to wrap them in \[ and \],
to mark them as non-printing characters.
if your CYAN is
CYAN="\e[0;36m"
you need to wrap it in \[ and \], like
CYAN="\[\e[0;36m\]"
otherwise, wrap the vars themselves in the prompt variables, like
PS2="\[$CYAN\]>\[$NOCOLOR\] "
see the comments here:
function __setprompt {
local SSH_IP="${SSH_CLIENT%% *}" # no need for echo/awk/sed
local SSH2_IP="${SSH2_CLIENT%% *}" # use parameter expansion instead
if [[ -n "$SSH2_IP" || -n "$SSH_IP" ]]; then # bash uses double brakets
local SSH_FLAG="#\h" # and the OR operator works inside
fi
PS1="\[$CYAN\][\u$SSH_FLAG:\[$BROWN\]\w\[$CYAN\]]\\$ \[$NOCOLOR\]" # dont mess with [ and ]
PS2="\[$CYAN\]>\[$NOCOLOR\] " # only wrap color vars in \[ and \]
PS4="\[$CYAN\]+\[$NOCOLOR\] " # single quotes will not expand $vars
}
__setprompt
also, have a look at PROMPT_COMMAND variable,
PROMPT_COMMAND
If set, the value is executed as a command prior to issuing each primary prompt.
and also note that by convension capital variable names are kept to be used by the environment

Resources