LinuxQuestions.org
Help answer threads with 0 replies.
Go Back   LinuxQuestions.org > Forums > Linux Forums > Linux - Newbie
User Name
Password
Linux - Newbie This Linux forum is for members that are new to Linux.
Just starting out and have a question? If it is not in the man pages or the how-to's this is the place!

Notices


Reply
  Search this Thread
Old 07-19-2012, 03:32 PM   #1
lleb
Senior Member
 
Registered: Dec 2005
Location: Florida
Distribution: CentOS/Fedora/Pop!_OS
Posts: 2,992

Rep: Reputation: 551Reputation: 551Reputation: 551Reputation: 551Reputation: 551Reputation: 551
BASH question about getting specific formatted display to the screen


i am playing around with getting the usage out to the display and here is what im testing with.

Code:
[ray@ray backup]$ cat TEST 
#!/bin/bash
echo -n "Would you like to read usage options?(Y/N) "
            read ANSWER
            if [[ $ANSWER = [Yy] ]]
            then
                USAGE >/tmp/netback.txt
                less /tmp/netback.txt
	else
		exit 2;
            fi


USAGE()
{
This is a test
   this is a test
          1) this is a test

     2) this is a test

[rbrunkow@sshserver ~]$ ls -l net*
-rwxrwxr-x 1 skerr vpnuser 43159 Jul 19 12:34 netbackup
-rw-r--r-- 1 skerr vpnuser  3832 Jun 22 12:01 netlist.txt
-rwxr-xr-x 1 skerr vpnuser   140 Mar  2  2011 netstate.sh

          3) still testing
               a. more testing
}
Problem is I either get nothing, or I get errors.

Code:
[ray@ray backup]$ vi TEST 
[ray@ray backup]$ ./TEST 
./TEST: line 29: warning: here-document at line 6 delimited by end-of-file (wanted `usage')
./TEST: line 30: syntax error: unexpected end of file
[ray@ray backup]$ vi TEST 
[ray@ray backup]$ ./TEST 
./TEST: line 27: warning: here-document at line 6 delimited by end-of-file (wanted `usage')
./TEST: line 28: syntax error: unexpected end of file
[ray@ray backup]$ ./TEST 
./TEST: line 27: warning: here-document at line 6 delimited by end-of-file (wanted `usage')
./TEST: line 28: syntax error: unexpected end of file
[ray@ray backup]$ :27
bash: :27: command not found...
[ray@ray backup]$ ^C
[ray@ray backup]$ vi TEST 
[ray@ray backup]$ ./TEST 
./TEST: line 8: syntax error near unexpected token `)'
./TEST: line 8: `          1) this is a test'
[ray@ray backup]$ vi TEST 
[ray@ray backup]$ ./TEST 
Would you like to read usage options?(Y/N) y
./TEST: line 6: USAGE: command not found
./TEST: line 15: syntax error near unexpected token `)'
./TEST: line 15: `          1) this is a test'
I had to put the echo command before the function. I was under the impression that BASH does not read a function unless it is called. Why would BASH read USAGE() with the 1) as an error. from the way I am thinking when you hit Y it cats the USAGE() out to a file, then should read it with less. no?

Code:
[ray@ray backup]$ ls -l /tmp
total 12
srwxrwxr-x  1 ray ray    0 Jun  1 08:50 890915C3CB4D8BCAC96AB1F459E7BCC571D2AFEB.19.0.1084.52_service_ipc
drwx------  2 ray ray 4096 Jul 19 05:33 CRX_75DAF8CB7768
drwxrwxr-x  2 ray ray 4096 Jul 18 16:00 lu862plu.tmp
-rw-rw-r--  1 ray ray    0 Jul 19 16:28 netback.txt
srwxrwxr-x  1 ray ray    0 May 30 15:19 OSL_PIPE_500_SingleOfficeIPC_9bbcfadd6b73776f9fe4435e4eebf93
drwx------. 2 ray ray 4096 May 30 15:18 pulse-UFqeNWZgUwyX
[ray@ray backup]$ cat /tmp/netback.txt 
[ray@ray backup]$
So it did create the temp file, but didnt populate it with any data.

Last edited by lleb; 07-19-2012 at 03:35 PM.
 
Old 07-19-2012, 03:40 PM   #2
lleb
Senior Member
 
Registered: Dec 2005
Location: Florida
Distribution: CentOS/Fedora/Pop!_OS
Posts: 2,992

Original Poster
Rep: Reputation: 551Reputation: 551Reputation: 551Reputation: 551Reputation: 551Reputation: 551
and if i put it in the normal format that I use with functions at the top of script and calls at bottom:

Code:
[ray@ray backup]$ cat TEST 
#!/bin/bash

USAGE()
{
This is a test
   this is a test
          1) this is a test

     2) this is a test

[rbrunkow@sshserver ~]$ ls -l net*
-rwxrwxr-x 1 skerr vpnuser 43159 Jul 19 12:34 netbackup
-rw-r--r-- 1 skerr vpnuser  3832 Jun 22 12:01 netlist.txt
-rwxr-xr-x 1 skerr vpnuser   140 Mar  2  2011 netstate.sh

          3) still testing
               a. more testing
}

echo -n "Would you like to read usage options?(Y/N) "
            read ANSWER
            if [[ $ANSWER = [Yy] ]]
            then
                USAGE >/tmp/netback.txt
                less /tmp/netback.txt
        else
                exit 2;
            fi

### exit 2 = user chose something other then [Yy] when prompted
[ray@ray backup]$ ./TEST 
./TEST: line 7: syntax error near unexpected token `)'
./TEST: line 7: `          1) this is a test'
why is it doing this?

Code:
[ray@ray backup]$ sh -xvv TEST 
#!/bin/bash

USAGE()
{
This is a test
   this is a test
          1) this is a test
TEST: line 7: syntax error near unexpected token `)'
TEST: line 7: `          1) this is a test'
 
Old 07-19-2012, 05:57 PM   #3
chrism01
LQ Guru
 
Registered: Aug 2004
Location: Sydney
Distribution: Rocky 9.2
Posts: 18,430

Rep: Reputation: 2788Reputation: 2788Reputation: 2788Reputation: 2788Reputation: 2788Reputation: 2788Reputation: 2788Reputation: 2788Reputation: 2788Reputation: 2788Reputation: 2788
It looks like you are trying to use HERE doc http://tldp.org/LDP/abs/html/here-docs.html & http://stackoverflow.com/questions/2...in-bash-script
 
1 members found this post helpful.
Old 07-19-2012, 09:31 PM   #4
grail
LQ Guru
 
Registered: Sep 2009
Location: Perth
Distribution: Arch
Posts: 10,036

Rep: Reputation: 3203Reputation: 3203Reputation: 3203Reputation: 3203Reputation: 3203Reputation: 3203Reputation: 3203Reputation: 3203Reputation: 3203Reputation: 3203Reputation: 3203
1. So the first thing to remember is that bash interprets from the top to the bottom. This means that you cannot call a function prior to it being defined. (error 1)

2. You create your USAGE function with lines like the following:
Code:
This is a test
Understanding that bash will interpret each line and process whether or not you are setting variables, calling functions or calling external commands, how would you expect
bash to interpret this line?? (error 2)

3. As chrism01 has pointed out, if utilising here documents (I am not really sure why this error came up as you do not appear to have started or ended a here document
anywhere in the snippet presented) please follow the links he has provided (here is another)

4. What if the user enters neither Y or N? What if they enter more than a single character?

5. Assuming we are getting our required response, unlike questions in 4 above, an easy solution to negate case is to force it to your desired case:
Code:
if [[ ${ANSWER,} = y ]] # you can use ^ and Y if you prefer upper case
6. The use of a temp file to then call less is also not required, as per the command line just pipe your function into less:
Code:
USAGE | less

Last edited by grail; 07-19-2012 at 09:33 PM.
 
1 members found this post helpful.
Old 07-20-2012, 09:13 AM   #5
lleb
Senior Member
 
Registered: Dec 2005
Location: Florida
Distribution: CentOS/Fedora/Pop!_OS
Posts: 2,992

Original Poster
Rep: Reputation: 551Reputation: 551Reputation: 551Reputation: 551Reputation: 551Reputation: 551
thanks guys, I will read those links and do some more testing. Always appreciate the help.
 
Old 07-20-2012, 10:42 AM   #6
lleb
Senior Member
 
Registered: Dec 2005
Location: Florida
Distribution: CentOS/Fedora/Pop!_OS
Posts: 2,992

Original Poster
Rep: Reputation: 551Reputation: 551Reputation: 551Reputation: 551Reputation: 551Reputation: 551
now im slightly confused after reading the links and an other script that i got the idea from:

Code:
USAGE()
{
cat <<-usage

######## Automatic Updates ######################
Automatic update has been added with netbackup version 2.1.
Any older versions need to be manually updated.
When netbackup 2.1 is downloaded and run, it will look for $HOME/.Update_enabled.
If not found, it will prompt for the root password and place an entry in sudo that will
allow the unpriviledged user to copy a new version of netbackup to /usr/bin, overwriting the
old one.
Auto update can be enable manually after the download of 2.1 (or later) by creating $HOME/.Update_enabled
and adding "/bin/cp /tmp/netbackup.sh /usr/bin/netbackup" to sudoers.

######## Virtual Pharmacist #######################
At setup, netbackup will now ask if it should start Virtual Pharmacist at the end of the backup.
Answering yes will add VirtRPH to the backup configuration file, ie;$HOME/.rsyncbackup.
If backup does not see this entry, Virtual Pharmacist will not be started.
This option can also be manually added by simply adding VirtRPH to the end of the appropriate
backup configuration file. MAKE SURE IT IS ADDED TO THE END OF THE LINE. Added anywhere else can cause
the backup to fail.

######## netbackup options ################################

Backup can use one of 3 transfer options. Each of those can be run in one of 3 ways.
1) Rsync to another nix box.
     netbackup rsync
     netbackup rsync_test
     netbackup rsync_auto

2) Rsync to a cifs/samba/windows share
     netbackup cifs
...


Double click on it to edit the value, put a check on the
Decimal radio button for the Base so that you can see the parameter value
as a decimal value and not a hexidecimal value.

Give the new key a value of 15 and reboot. If that is not enough, raise it a litte to let's say 18
and then reboot again. The problem is solved. Go mount your samba shares.
usage
}
Then is later called:
Code:
echo "Option not recognized"
            echo -n "Would you like to read usage options?(Y/N) "
            read ANSWER
            if [[ $ANSWER = [Yy] ]]
            then
                USAGE >/tmp/netback.txt
                less /tmp/netback.txt
            fi
            exit 1 ;;
When you run that script with usage flag (netbackup usage) it prints out exactly including ), spaces, etc... with zero problems. Why then does my script with the same type of ) and other plan text error?
 
Old 07-20-2012, 11:41 AM   #7
Reuti
Senior Member
 
Registered: Dec 2004
Location: Marburg, Germany
Distribution: openSUSE 15.2
Posts: 1,339

Rep: Reputation: 260Reputation: 260Reputation: 260
Their usage definition includes some important lines which are missing in your script. Try:
Code:
USAGE()
{
cat <<-usage
foobar
    baz
usage
}
 
1 members found this post helpful.
Old 07-20-2012, 12:04 PM   #8
grail
LQ Guru
 
Registered: Sep 2009
Location: Perth
Distribution: Arch
Posts: 10,036

Rep: Reputation: 3203Reputation: 3203Reputation: 3203Reputation: 3203Reputation: 3203Reputation: 3203Reputation: 3203Reputation: 3203Reputation: 3203Reputation: 3203Reputation: 3203
Quote:
Why then does my script with the same type of ) and other plan text error?
What error?
 
Old 07-20-2012, 12:22 PM   #9
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
Let's try to make things less confusing by not using the same name for the function and the heredoc.

Code:
usage() {
	cat <<-HEREDOC
	   This is the text that is to
	be printed by the function.
	HEREDOC
}
The HEREDOC lines specify the beginning and ending of the text that gets fed into cat.

I also made a couple of other changes here. First, Since environment variables are generally all upper-case, it's good practice to keep your own user variables, and in this case function names, in lower-case or mixed-case to help differentiate them.

Second, the "<<-" here document syntax allows you to use tabs to indent the strings, without affecting the output. It helps to make the function more readable. Be careful to only use tabs for the script-syntax indentations, and use regular spaces for the actual text formatting indentations.

I personally don't like to use heredocs for this kind of thing, since it can be so picky about the formatting, and also requires using the external cat command. I generally just set up a series of echo or printf commands or similar, where I can manually fiddle with the formatting of every line.

Edit: oh yeah, I almost forgot. When parsing user input from read, it's usually better to use a case statement, rather than if's.

Code:
case $answer in

	[yY]*)  usage | less ;; #no need to use an external file

	    *)  exit 2 ;;

esac

Last edited by David the H.; 07-20-2012 at 12:27 PM. Reason: addendum
 
1 members found this post helpful.
Old 07-20-2012, 12:51 PM   #10
lleb
Senior Member
 
Registered: Dec 2005
Location: Florida
Distribution: CentOS/Fedora/Pop!_OS
Posts: 2,992

Original Poster
Rep: Reputation: 551Reputation: 551Reputation: 551Reputation: 551Reputation: 551Reputation: 551
ahh, that is much more clear, thank you both.

will report back on my success/fail in a bit.
 
Old 07-20-2012, 01:00 PM   #11
lleb
Senior Member
 
Registered: Dec 2005
Location: Florida
Distribution: CentOS/Fedora/Pop!_OS
Posts: 2,992

Original Poster
Rep: Reputation: 551Reputation: 551Reputation: 551Reputation: 551Reputation: 551Reputation: 551
PERFECT, you guys rule.

Code:
[ray@ray backup]$ cat TEST 
#!/bin/bash

USAGE()
{
	cat <<-HEREDOC
This is a test
   this is a test
          1) this is a test

     2) this is a test

[rbrunkow@sshserver ~]$ ls -l net*
-rwxrwxr-x 1 skerr vpnuser 43159 Jul 19 12:34 netbackup
-rw-r--r-- 1 skerr vpnuser  3832 Jun 22 12:01 netlist.txt
-rwxr-xr-x 1 skerr vpnuser   140 Mar  2  2011 netstate.sh

          3) still testing
               a. more testing
		HEREDOC
}

echo -n "Would you like to read usage options?(Y/N) "
	read answer

case $answer in
	[yY]*) USAGE | less ;;
	    *) exit 2 ;;
esac

### exit 2 = user chose something other then [Yy] when prompted
More importantly I understand what I was doing wrong. By leaving out the <<-HEREDOC at top/bottom of section nothing was working. I also like the case/esac section. That is very clean. Still a little hard for ME to read, but that is just my lack of coding skill.

I also learned that i needed to leave the:

Code:
 echo -n "foo "
     read answer
in order for the case to function as that is the variable creator. I like that. Now I can add a 'h' for my getopts on the script I was working on this for to print out details on what/how to do things for the backup script im working on.

Is there a way when using getopts to have -h and --help perform the same function? or just leave it at -h and be done with it?
 
Old 07-20-2012, 01:28 PM   #12
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
No, getopts isn't designed to handle long-form options. There is the external getopt command, but it's more complex to set up, and not really recommended. You're really better off just using short options only.

BTW, the tab-indent feature of heredocs is there so that you can format your scripts cleanly. Either indent every line of it with the same number of tabs, or don't tab-indent it at all.

And read the heredoc documentation that was supplied to you before.
 
1 members found this post helpful.
Old 07-20-2012, 02:12 PM   #13
lleb
Senior Member
 
Registered: Dec 2005
Location: Florida
Distribution: CentOS/Fedora/Pop!_OS
Posts: 2,992

Original Poster
Rep: Reputation: 551Reputation: 551Reputation: 551Reputation: 551Reputation: 551Reputation: 551
again thanks for the info.

from what I understood of the heredoc link

<<-foo tells it to ignore all tab indents as whitespce, but if i dont use the <<- and just use << will it keep the tab formatting?

That was something i was not 100% clear on with the documentation. i am guessing there is also a manpage for heredoc.
 
Old 07-20-2012, 02:16 PM   #14
lleb
Senior Member
 
Registered: Dec 2005
Location: Florida
Distribution: CentOS/Fedora/Pop!_OS
Posts: 2,992

Original Poster
Rep: Reputation: 551Reputation: 551Reputation: 551Reputation: 551Reputation: 551Reputation: 551
this is my confusion on that part:

Quote:
If we want to be able to indent the here document, we can prefix the delimiter word with a - (hyphen):


if ...
while ....
someprogram <<-WORD
this is
an indented
here document
WORD
done
fi
In this form, all leading tab characters (not spaces!) will be removed. There is no provision for removing leading spaces, or leading tabs-and-spaces. (Recall the syntactic restrictions of Makefiles, and you'll be OK.)
at first it states that if you WANT to indent then add the '-', but at the end it indicates that all leading tab characters will be removed. that to me is a direct contradiction in terms. you are either going to indent, or you are not. can do both at same time as the latter removes the first.
 
Old 07-20-2012, 02:25 PM   #15
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
html rendering removes initial whitespace, and collapses all the rest into single spaces. You need to use code tags to protect formatting like the above.

There's no inconsistency in the explanation. You just aren't reading it correctly.

If you use "<<" then all whitespace is treated as literal. The tabs will become part of the output. The heredoc itself must be formatted flush with the left edge. The closing string in particular must then not have any whitespace or other characters around it. It will have to exist all alone on a line.

The extra "-" tells it to remove any initial tabs from each line before sending the rest to stdout. This lets you tab-indent everything, but of course you can't format the contents with initial tabs then, although you can use them later in the line. The closing string can also be indented with initial tabs, but it still cannot have any other text on the line.


Finally, also note that if you quote the starting string, it will protect any variables or other parameters from expanding inside the heredoc. Otherwise they will be substituted first. And remember that quotemarks aren't processed inside the heredoc either.


Edit: Don't get confused between the formatting of the heredoc and the formatting of the text it contains! The tab indentation thing lets you do the former, without affecting the latter.

Maybe this will help you:
Code:
<tab><tab>cat <<-HEREDOC
<tab><tab>  This line is indented by two spaces
<tab><tab>This line is not indented at all
<tab><tab>HEREDOC

#output
  This line is indented by two spaces
This line is not indented at all

##########

cat <<HEREDOC
  This line is indented by two spaces
This line is not indented at all
HEREDOC

#output
  This line is indented by two spaces
This line is not indented at all

##########

cat <<HEREDOC
<tab><tab>  This line is indented by two spaces
<tab><tab>This line is not indented at all
<tab><tab>HEREDOC

#output
#broken because of the tabs in front of the ending string,
#but if it worked, it would produce this:
<tab><tab>  This line is indented by two spaces
<tab><tab>This line is not indented at all

Last edited by David the H.; 07-20-2012 at 02:45 PM. Reason: changes and additions
 
  


Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search

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
[SOLVED] bash - question about grepping a specific time period xmichielx Programming 5 04-07-2015 11:44 PM
[SOLVED] I have a specific linux bash question about variables and possible hexadecimals. darkstarbyte Linux - Software 3 11-13-2011 03:20 AM
how to add numbers in a formatted file via a bash script? zero79 Linux - General 8 12-24-2010 05:48 PM
Bash script question (sending output to specific lines) ptcl Linux - Software 9 11-21-2006 03:53 AM
How to display formatted floats rkrijger Linux - Software 4 10-21-2003 08:52 AM

LinuxQuestions.org > Forums > Linux Forums > Linux - Newbie

All times are GMT -5. The time now is 12:14 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