LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Linux - General (https://www.linuxquestions.org/questions/linux-general-1/)
-   -   BASH Scripting : Quoting Variables Catch 22!! (https://www.linuxquestions.org/questions/linux-general-1/bash-scripting-quoting-variables-catch-22-a-937442/)

Bill Gates 666 03-31-2012 01:34 PM

BASH Scripting : Quoting Variables Catch 22!!
 
Hi

I'm trying to fix a bug (the erroneous striping of \ escape characters in unit names) in the ARCH-Linux SystemD bash-completion script.

The crucial line is:
Code:

COMPREPLY=( $(compgen -W "$comps" -- "$cur") )
Basically I want to write something like:
Code:

COMPREPLY=( $(compgen -W '$comps' -- '$cur') )
so I get "protection" for the \ escape character (which starts to get swolled up otherwise!!) but also get expansion for variables $comps and $cur (which the ' quote prevents).

I've tried (a gross hack:banghead:) creating the string first, then executing it, but =Fail - something like:
Code:

local command="compgen -W '$comps' -- '$cur'"
COMPREPLY=( $(`$command`) )

$COMPREPLY is just an empty string each time... $command contains the correct characters...

Any BASH experts out there able to help out a noob?? :cry:

Mr Gates

jaybutts 04-01-2012 08:37 AM

Im not really sure the extra set of parenthesis is need but here some things you can try aside from that:
try:
Code:

COMPREPLY=( $(compgen -W "${comps}" -- "${cur}") )
Again not sure why you have the extra paranthesis, simply try this:

Code:

COMPREPLY=$(compgen -W "${comps}" -- "${cur}")
Aside form that I also don't know what the -- does? or what your code really does, it might help to try and explain it a little more.

Bill Gates 666 04-01-2012 09:46 AM

Quote:

Originally Posted by jaybutts (Post 4641963)
Aside form that I also don't know what the -- does? or what your code really does, it might help to try and explain it a little more.

@jaybutts

Sorry my bad for not giving enough details!!

The extra bracketing is convert a returned list of SystemD subcommands or Unit names to an array of potential responses! Just to re-iterate it's not my code at all. Like I mentioned it's the ARCH-Linux SystemD bash-completion script. All the script does is to provide command line completion for SystemD commands entered in a BASH shell (i.e. when you pressed the TAB key it tries to match against all valid responses).

With your suggestion (remove extra bracketing) the command-line completion variable $COMPREPLY will contain all the potential responses in a big list (individual entries separated by spaces). So that is not going to work!
Code:

$COMPREPLAY='enable isolate delete start daemon-reexec daemon-reload default dot dump emergency exit halt kexec list-jobs list-units list-unit-files poweroff reboot rescue show-environment disable reenable snapshot load link restart reload-or-restart set-environment unset-environment cancel unmask stop condstop kill try-restart condrestart is-active is-enabled status show mask preset reload condreload reload-or-try-restart force-reload reset-failed'

The desired behaviour is to return an array containing individual valid responses, e.g.:
Code:

$COMPREPLAY[0]='enable'
$COMPREPLAY[1]='isolate'
...


The problem I am trying to tackle is that SystemD Unit names have to use a name mangling system. If they contain (normally command-line escaped) things such as brackets, etc then these must be converted to escaped HEX code equivalents. The '-' character is used to represent Linux directory back-slashes ('/') - so must also be mangled.

E.g.:
Code:

mnt-robs\x2dserver-external-Music.mount
would specify a mount-point Unit (for any specified filesystem) in the following (real Linux FS hierarchy) mount-point:
Code:

/mnt/robs-server/external/Music
(where '\x2d'=HEX character code for '-')

See here for more info on the name mangling used.


I take the input Unit names and use awk mangle it to:
Code:

/mnt/robs\\x2dserver/external/Music
(doubling the number of '\' forward slashes so that the name works on the BASH commandline - since '\' characters must be escaped).

The problem is that the double quote " symbol around variables ${comps} and ${cur} results in them being transformed by the shell with '\\' combinations being replaced by '\'. So I would get back to:
Code:

/mnt/robs\x2dserver/external/Music
When this is passed as a Unit name to the SystemD systemctl command

E.g.
Code:

sudo systemctl enable /mnt/robs\x2dserver/external/Music
would fail as an invalid Unit name as the BASH shell interprets the '\x' as an escaped 'x' character.

What I want the commandline completion to do is give:
Code:

sudo systemctl enable /mnt/robs\\x2dserver/external/Music
Any thoughts? Sadly I am a total BASH scripting noob... :scratch:
Bob

alinas 04-05-2012 11:22 AM

Not sure I understood the details, but it feels like a potential job for eval.


All times are GMT -5. The time now is 02:35 AM.