mirror of https://github.com/tLDP/LDP
149 lines
4.7 KiB
Bash
149 lines
4.7 KiB
Bash
#! /bin/bash
|
|
# protect_literal.sh
|
|
|
|
# set -vx
|
|
|
|
:<<-'_Protect_Literal_String_Doc'
|
|
|
|
Copyright (c) Michael S. Zick, 2003; All Rights Reserved
|
|
License: Unrestricted reuse in any form, for any purpose.
|
|
Warranty: None
|
|
Revision: $ID$
|
|
|
|
Documentation redirected to the Bash no-operation.
|
|
Bash will '/dev/null' this block when the script is first read.
|
|
(Uncomment the above set command to see this action.)
|
|
|
|
Remove the first (Sha-Bang) line when sourcing this as a library
|
|
procedure. Also comment out the example use code in the two
|
|
places where shown.
|
|
|
|
|
|
Usage:
|
|
_protect_literal_str 'Whatever string meets your ${fancy}'
|
|
Just echos the argument to standard out, hard quotes
|
|
restored.
|
|
|
|
$(_protect_literal_str 'Whatever string meets your ${fancy}')
|
|
as the right-hand-side of an assignment statement.
|
|
|
|
Does:
|
|
As the right-hand-side of an assignment, preserves the
|
|
hard quotes protecting the contents of the literal during
|
|
assignment.
|
|
|
|
Notes:
|
|
The strange names (_*) are used to avoid trampling on
|
|
the user's chosen names when this is sourced as a
|
|
library.
|
|
|
|
_Protect_Literal_String_Doc
|
|
|
|
# The 'for illustration' function form
|
|
|
|
_protect_literal_str() {
|
|
|
|
# Pick an un-used, non-printing character as local IFS.
|
|
# Not required, but shows that we are ignoring it.
|
|
local IFS=$'\x1B' # \ESC character
|
|
|
|
# Enclose the All-Elements-Of in hard quotes during assignment.
|
|
local tmp=$'\x27'$@$'\x27'
|
|
# local tmp=$'\''$@$'\'' # Even uglier.
|
|
|
|
local len=${#tmp} # Info only.
|
|
echo $tmp is $len long. # Output AND information.
|
|
}
|
|
|
|
# This is the short-named version.
|
|
_pls() {
|
|
local IFS=$'x1B' # \ESC character (not required)
|
|
echo $'\x27'$@$'\x27' # Hard quoted parameter glob
|
|
}
|
|
|
|
# :<<-'_Protect_Literal_String_Test'
|
|
# # # Remove the above "# " to disable this code. # # #
|
|
|
|
# See how that looks when printed.
|
|
echo
|
|
echo "- - Test One - -"
|
|
_protect_literal_str 'Hello $user'
|
|
_protect_literal_str 'Hello "${username}"'
|
|
echo
|
|
|
|
# Which yields:
|
|
# - - Test One - -
|
|
# 'Hello $user' is 13 long.
|
|
# 'Hello "${username}"' is 21 long.
|
|
|
|
# Looks as expected, but why all of the trouble?
|
|
# The difference is hidden inside the Bash internal order
|
|
#+ of operations.
|
|
# Which shows when you use it on the RHS of an assignment.
|
|
|
|
# Declare an array for test values.
|
|
declare -a arrayZ
|
|
|
|
# Assign elements with various types of quotes and escapes.
|
|
arrayZ=( zero "$(_pls 'Hello ${Me}')" 'Hello ${You}' "\'Pass: ${pw}\'" )
|
|
|
|
# Now list that array and see what is there.
|
|
echo "- - Test Two - -"
|
|
for (( i=0 ; i<${#arrayZ[*]} ; i++ ))
|
|
do
|
|
echo Element $i: ${arrayZ[$i]} is: ${#arrayZ[$i]} long.
|
|
done
|
|
echo
|
|
|
|
# Which yields:
|
|
# - - Test Two - -
|
|
# Element 0: zero is: 4 long. # Our marker element
|
|
# Element 1: 'Hello ${Me}' is: 13 long. # Our "$(_pls '...' )"
|
|
# Element 2: Hello ${You} is: 12 long. # Quotes are missing
|
|
# Element 3: \'Pass: \' is: 10 long. # ${pw} expanded to nothing
|
|
|
|
# Now make an assignment with that result.
|
|
declare -a array2=( ${arrayZ[@]} )
|
|
|
|
# And print what happened.
|
|
echo "- - Test Three - -"
|
|
for (( i=0 ; i<${#array2[*]} ; i++ ))
|
|
do
|
|
echo Element $i: ${array2[$i]} is: ${#array2[$i]} long.
|
|
done
|
|
echo
|
|
|
|
# Which yields:
|
|
# - - Test Three - -
|
|
# Element 0: zero is: 4 long. # Our marker element.
|
|
# Element 1: Hello ${Me} is: 11 long. # Intended result.
|
|
# Element 2: Hello is: 5 long. # ${You} expanded to nothing.
|
|
# Element 3: 'Pass: is: 6 long. # Split on the whitespace.
|
|
# Element 4: ' is: 1 long. # The end quote is here now.
|
|
|
|
# Our Element 1 has had its leading and trailing hard quotes stripped.
|
|
# Although not shown, leading and trailing whitespace is also stripped.
|
|
# Now that the string contents are set, Bash will always, internally,
|
|
#+ hard quote the contents as required during its operations.
|
|
|
|
# Why?
|
|
# Considering our "$(_pls 'Hello ${Me}')" construction:
|
|
# " ... " -> Expansion required, strip the quotes.
|
|
# $( ... ) -> Replace with the result of..., strip this.
|
|
# _pls ' ... ' -> called with literal arguments, strip the quotes.
|
|
# The result returned includes hard quotes; BUT the above processing
|
|
#+ has already been done, so they become part of the value assigned.
|
|
#
|
|
# Similarly, during further usage of the string variable, the ${Me}
|
|
#+ is part of the contents (result) and survives any operations
|
|
# (Until explicitly told to evaluate the string).
|
|
|
|
# Hint: See what happens when the hard quotes ($'\x27') are replaced
|
|
#+ with soft quotes ($'\x22') in the above procedures.
|
|
# Interesting also is to remove the addition of any quoting.
|
|
|
|
# _Protect_Literal_String_Test
|
|
# # # Remove the above "# " to disable this code. # # #
|
|
|
|
exit 0
|