LinuxQuestions.org
Latest LQ Deal: Latest LQ Deals
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 07-04-2019, 05:34 AM   #1
Reuti
Senior Member
 
Registered: Dec 2004
Location: Marburg, Germany
Distribution: openSUSE 15.2
Posts: 1,339

Rep: Reputation: 260Reputation: 260Reputation: 260
" in a Bash here-document


Hi,

I stumbled about an issue where quotation marks are either removed or output including the escape character:

Code:
CMDOPT_F=1
FILES="MRCONEE MDCINT"
cat <<EOF > script
line 1
pam${CMDOPT_F+ --get="${FILES}"}
line 3
EOF
cat script
will result in:
Code:
line 1
pam --get=MRCONEE MDCINT
line 3
which is the result as the quotation marks are removed – okay. So the variant:

Code:
CMDOPT_F=1
FILES="MRCONEE MDCINT"
cat <<EOF > script
line 1
pam${CMDOPT_F+ --get=\"${FILES}\"}
line 3
EOF
cat script
might help, but the output is:
Code:
line 1
pam --get=\"MRCONEE MDCINT\"
line 3
I would have expected that the escape characters are removed, once they were used.

I succeeded by using a variable for the quotation mark:
Code:
QUOTE=\"
CMDOPT_F=1
FILES="MRCONEE MDCINT"
cat <<EOF > script
line 1
pam${CMDOPT_F+ --get=${QUOTE}${FILES}${QUOTE}}
line 3
EOF
cat script
Code:
line 1
pam --get="MRCONEE MDCINT"
line 3
which is the desired ouptut. But I’m still puzzled, why the \" ended up in the script in the second case.

-- Reuti
 
Old 07-04-2019, 05:45 AM   #2
Keith Hedger
Senior Member
 
Registered: Jun 2010
Location: Wiltshire, UK
Distribution: Void, Linux From Scratch, Slackware64
Posts: 3,150

Rep: Reputation: 856Reputation: 856Reputation: 856Reputation: 856Reputation: 856Reputation: 856Reputation: 856
it seems to be this construct
Code:
pam${CMDOPT_F+ --get="${FILES}"}
Use
Code:
pam --get="$FILES"
Instead gives
Code:
#!/bin/bash -e

#©keithhedger Thu 4 Jul 11:39:22 BST 2019 kdhedger68713@gmail.com
CMDOPT_F=1
FILES="MRCONEE MDCINT"
cat <<EOF > script
line 1
#pam${CMDOPT_F+ --get="${FILES}"}
pam --get="$FILES"
line 3
EOF
cat script

line 1
pam --get="MRCONEE MDCINT"
line 3
 
1 members found this post helpful.
Old 07-04-2019, 05:59 AM   #3
Reuti
Senior Member
 
Registered: Dec 2004
Location: Marburg, Germany
Distribution: openSUSE 15.2
Posts: 1,339

Original Poster
Rep: Reputation: 260Reputation: 260Reputation: 260
Quote:
Originally Posted by Keith Hedger View Post
it seems to be this construct
Code:
pam${CMDOPT_F+ --get="${FILES}"}
Use
Code:
pam --get="$FILES"
Hi Keith,

Thx for looking into this. The construct ${parameter+word} is used here, as I want the --get option only in case CMDOPT_F was set. Otherwise nothing should be appended. Sorry for neglecting this prerequisite.

-- Reuti
 
Old 07-04-2019, 08:40 AM   #4
Keith Hedger
Senior Member
 
Registered: Jun 2010
Location: Wiltshire, UK
Distribution: Void, Linux From Scratch, Slackware64
Posts: 3,150

Rep: Reputation: 856Reputation: 856Reputation: 856Reputation: 856Reputation: 856Reputation: 856Reputation: 856
in which case you are using the wrong construct this is the correct way to set a default value to a variable in bash
Code:
echo ${MYVAR:-"Default Val"}
Default Val
MYVAR="another val"
echo ${MYVAR:-"Default Val"}
another val
 
1 members found this post helpful.
Old 07-04-2019, 10:43 AM   #5
David the H.
Bash Guru
 
Registered: Jun 2004
Location: Osaka, Japan
Distribution: Arch + Xfce
Posts: 6,852

Rep: Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037
There are four variations for alternate values in variable expansion. From man bash:

Code:
${parameter:-word}
    Use Default Values.  If parameter is unset or null, the expansion of word is substituted.  Otherwise, the value of parameter is substituted.

${parameter:=word}
    Assign  Default  Values.   If  parameter  is  unset or null, the expansion of word is assigned to parameter.  The value of parameter is then substituted.  Positional parameters and special parameters may not be assigned to in this way.

${parameter:?word}
    Display  Error if Null or Unset.  If parameter is null or unset, the expansion of word (or a message to that effect if word is not present) is written to the standard error and the shell, if it is not interactive, exits.  Otherwise, the value of parameter is substituted.

${parameter:+word}
    Use Alternate Value.  If parameter is null or unset, nothing is substituted, otherwise the expansion of word is substituted.
If the colon is omitted, it will only test for empty values, and not react to null (unset) variables.


You can nest quotes inside parameter substitutions, so I believe you want to use the version I supply below.



As for heredocs, I have personally come to dislike them, for the most part. I find them hard to set up correctly and awkward to read. My preference is usually to use an array, with each index holding one line of text.

Code:
CMDOPT_F=1
FILES='MRCONEE MDCINT'

## start script array ##

script[0]='line 1'
script[1]="pam${CMDOPT_F:+" --get='$FILES'"}"
script[2]='line 3'

## end script array ##

printf '%s\n' "${script[@]}" > script
Result:
Code:
line 1
pam --get='MRCONEE MDCINT'
line 3
BTW, you might just skip the extra variable and test the FILES variable directly, if that would suit you better.

Code:
myscript+=( "pam${FILES:+" --get='$FILES'"}" )
 
2 members found this post helpful.
Old 07-04-2019, 02:25 PM   #6
Keith Hedger
Senior Member
 
Registered: Jun 2010
Location: Wiltshire, UK
Distribution: Void, Linux From Scratch, Slackware64
Posts: 3,150

Rep: Reputation: 856Reputation: 856Reputation: 856Reputation: 856Reputation: 856Reputation: 856Reputation: 856
[QUOTE=David the H.;6011913]There are four variations for alternate values in variable expansion. From man bash:

Code:
...

${parameter:=word}
    Assign  Default  Values.   If  parameter  is  unset or null, the expansion of word is assigned to parameter.  The value of parameter is then substituted.  Positional parameters and special parameters may not be assigned to in this way.

${parameter:?word}
    Display  Error if Null or Unset.  If parameter is null or unset, the expansion of word (or a message to that effect if word is not present) is written to the standard error and the shell, if it is not interactive, exits.  Otherwise, the value of parameter is substituted.

${parameter:+word}
    Use Alternate Value.  If parameter is null or unset, nothing is substituted, otherwise the expansion of word is substituted.
...

Not seen these before, is it new? You learn something new every day
 
Old 07-04-2019, 11:55 PM   #7
grail
LQ Guru
 
Registered: Sep 2009
Location: Perth
Distribution: Manjaro
Posts: 10,006

Rep: Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191
Is there a reason you cannot switch to single quotes?
This worked for me:
Code:
CMDOPT_F=1
FILES="MRCONEE MDCINT"
cat <<EOF>script
line 1
pam${CMDOPT_F+ --get='${FILES}'}
line 3
EOF
cat script
Shellcheck does complain about it but I don't think it understands here-doc rules
 
1 members found this post helpful.
Old 08-01-2019, 12:23 PM   #8
MadeInGermany
Senior Member
 
Registered: Dec 2011
Location: Simplicity
Posts: 2,790

Rep: Reputation: 1201Reputation: 1201Reputation: 1201Reputation: 1201Reputation: 1201Reputation: 1201Reputation: 1201Reputation: 1201Reputation: 1201
What bash version?
I have seen such incorrect parsing in bash-3 that got corrected in bash-4.
 
Old 08-02-2019, 03:11 PM   #9
Reuti
Senior Member
 
Registered: Dec 2004
Location: Marburg, Germany
Distribution: openSUSE 15.2
Posts: 1,339

Original Poster
Rep: Reputation: 260Reputation: 260Reputation: 260
Quote:
Originally Posted by grail View Post
Is there a reason you cannot switch to single quotes?
No, but this was indeed the cure. Nevertheless I was looking for an explanation about the observed behavior.

-- Reuti
 
Old 08-02-2019, 03:13 PM   #10
Reuti
Senior Member
 
Registered: Dec 2004
Location: Marburg, Germany
Distribution: openSUSE 15.2
Posts: 1,339

Original Poster
Rep: Reputation: 260Reputation: 260Reputation: 260
Quote:
Originally Posted by MadeInGermany View Post
What bash version?
I have seen such incorrect parsing in bash-3 that got corrected in bash-4.
It was version 4.2.42(1), but I even compiled just the 5.0 version and the effect is still the same.

-- Reuti
 
  


Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
id "2", "3", "4", "5"respawning too fast: disabled for 5 minutes cesarff2000 Linux - Newbie 3 06-27-2012 10:50 PM
[SOLVED] Replace a string @CURRANGE("***","***") to @CURRANGE("xxx","xxx") in a file mavadikarmayur Linux - Newbie 3 03-26-2012 08:32 AM
"001" and "0012" converted to "01", "12". How? stf92 Programming 7 07-08-2011 06:55 PM
Help With Java Problem Please"""""""""""" suemcholan Linux - Newbie 1 04-02-2008 06:02 PM
New To """"l I N U X"""" chawla_ab LinuxQuestions.org Member Intro 3 01-22-2006 11:03 AM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 09:19 AM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration