LinuxQuestions.org
Welcome to the most active Linux Forum on the web.
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 09-09-2007, 11:10 AM   #1
MS3FGX
LQ Guru
 
Registered: Jan 2004
Location: NJ, USA
Distribution: Slackware, Debian
Posts: 5,852

Rep: Reputation: 361Reputation: 361Reputation: 361Reputation: 361
Handling newlines in Bash


I have a slight aesthetic problem that I can't seem to wrap my mind around, and I was hoping I might get some input on it here.

Basically, I want to be able to print a status message, execute a command, and then follow it with a message about it succeeding on the same line. That is easy enough to do, I just have something like this:

Code:
echo -n "Running command..."
command 2>/dev/null
echo "Done!"
That works fine, but the problem comes in when the task fails. In my Bash scripts I use an error handler, so it actually looks like this:

Code:
ErrorMsg ()
{
# ErrorMsg <Error Type> <Error Message>
# Displays either a minor (warning) or critical error, exiting on an critical.
if [ "$1" == "ERR" ]; then
        # This is a critical error, game over.
        echo "  ERROR: $2"
        exit 1
elif [ "$1" == "WRN" ]; then
        # This is only a warning, script continues but may not work fully.
        echo "  WARNING: $2"
fi
}

echo -n "Running command..."
command 2>/dev/null || ErrorMsg ERR "The command has failed!"
echo "Done!"
Functionally, this works. But the problem is that since I printed the first line "Running command..." without the newline, my error message follows it instead of being below and to the right as I want.

So it looks like:

Code:
Running command...   ERROR: The command has failed!
Instead of:

Code:
Running command...
   ERROR: The command has failed!
Now, the obvious solution was to change my echo lines in ErrorMsg () to:

Code:
echo -e "\n  ERROR: $2"
BUT, here is the problem. I also want to call ErrorMsg in situations where I have not previously printed a line without a newline, in which case, using this method makes the error print a blank line first.

So basically, my problem is that I want to be able to print the error line where I want it, in either situation. It seems that I need some method of detecting if the previous line was ended or not, and then act accordingly.

My other idea was to give the newline command to ErrorMsg, so it would look like:

Code:
ErrorMsg ERR "\nThis is an error."
But because of the way I am handling it, this won't work properly since the "ERROR:" part is always printed regardless of the line I give it to print.

So it comes out like:

Code:
ERROR:
This is an error.
Terrible.

I was thinking that I could do something where I check if the first characters of the string are "\n", then strip them adjust the echo command accordingly? Like:

Code:
if $string starts with \n; then
     strip \n from $string
     echo -e "\n ERROR: $string"
else
     echo " ERROR: $string"
fi
Is there a better way to handle this issue? I don't actually know how to strip the characters from the string and such, but I am sure it can't be too difficult. I just want to know if there is a better method to work this out before I start playing around with my own concept.

P.S.

Yes, I am aware this is a rather ridiculous question in the grand scheme of things, but I am a bit obsessive and it bothers me that my error message don't all look the same with the current method.
 
Old 09-09-2007, 11:36 AM   #2
druuna
LQ Veteran
 
Registered: Sep 2003
Posts: 10,532
Blog Entries: 7

Rep: Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405
Hi,

I've been trying to duplicate your problem and I can't (using single command to substitute command 2>/dev/null part).

The only thing unclear seems to be this 'command' part of the script, could it be that this is the 'problem'? Could it be that besides the message sent to stderr there's also something going to stdout (piped commands come to mind)?

Ok, that doesn't solve your problem but could point to the reason for this behavior.

If you want cursor position control you could take a look at tput. It's probably a bit more work to implement, but if you like aesthetic output it could be worth the effort.

Hope this helps.
 
Old 09-09-2007, 11:49 AM   #3
ilikejam
Senior Member
 
Registered: Aug 2003
Location: Glasgow
Distribution: Fedora / Solaris
Posts: 3,109

Rep: Reputation: 97
Why not addan argument to ErrorMsg to tell it whether or not to print a newline before the error?

Dave
 
Old 09-09-2007, 12:31 PM   #4
MS3FGX
LQ Guru
 
Registered: Jan 2004
Location: NJ, USA
Distribution: Slackware, Debian
Posts: 5,852

Original Poster
Rep: Reputation: 361Reputation: 361Reputation: 361Reputation: 361
I was considering that as well, simply make a third variable that acts as a bool determining whether or not to do a newline. I was looking for something a bit more automated, if nothing else for the sake of elegance, but that is certainly a fallback option; and really my best one I suppose. Easier than playing around with stripping the newlines off the string and such,

Quote:
I've been trying to duplicate your problem and I can't (using single command to substitute command 2>/dev/null part).
Perhaps the command you were trying wasn't failing? It won't run ErrorMsg unless it fails. As an example, here is what happens when we run a command that will definitely fail (you could do the same with just "false", but I didn't think of that until just now):

Script:
Code:
ErrorMsg ()
{
# ErrorMsg <Error Type> <Error Message>
# Displays either a minor (warning) or critical error, exiting on an critical.
if [ "$1" == "ERR" ]; then
        # This is a critical error, game over.
        echo "  ERROR: $2"
        #exit 1
elif [ "$1" == "WRN" ]; then
        # This is only a warning, script continues but may not work fully.
        echo "  WARNING: $2"
fi
}


# In the real usage, the "Done!"'s would never print (ErrorMsg would bail out),
# but there are here for illustration, since in the real script the commands
# should be succeeding

clear
echo "This is what happens when there is no newline:"

echo -n "Running bogus ping..."
ping -w 1 1.0.0.0 >/dev/null || ErrorMsg ERR "The command has failed!"
#echo "Done!"

echo
echo "This is what it should look like:"

echo "Running bogus ping..."
ping -w 1 1.0.0.0 >/dev/null || ErrorMsg ERR "The command has failed!"
#echo "Done!"
Output:
Code:
This is what happens when there is no newline:
Running bogus ping...  ERROR: The command has failed!

This is what it should look like:
Running bogus ping...
  ERROR: The command has failed!
 
Old 09-09-2007, 01:30 PM   #5
druuna
LQ Veteran
 
Registered: Sep 2003
Posts: 10,532
Blog Entries: 7

Rep: Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405
Hi,

Quote:
Perhaps the command you were trying wasn't failing?
Yep, they failed.

Your second example isn't the same as the first (stdout vs stderr):

First:
command 2>/dev/null || ErrorMsg ERR "The command has failed!"

Second:
ping -w 1 1.0.0.0 >/dev/null || ErrorMsg ERR "The command has failed!"

The second example fails to create the correct error message on both ping commands.

If I change the >/dev/null to 2>/dev/null, only the second ping fails to create the correct error message (I removed the clear command):
Code:
$ ./error.on.same.line.2.sh 
This is what happens when there is no newline:
Running bogus ping...  ERROR: The command has failed!

This is what it should look like:
Running bogus ping...
  ERROR: The command has failed!
Which bash version are you using?

$ bash --version
GNU bash, version 3.1.17(1)-release (i686-pc-linux-gnu)
Copyright (C) 2005 Free Software Foundation, Inc.
 
Old 09-09-2007, 01:40 PM   #6
jozyba
Member
 
Registered: Sep 2007
Distribution: Debian Etch, Lenny, Lenny/Sid
Posts: 31

Rep: Reputation: 15
Does this work the way you want it to?
Code:
ErrorMsg ()
{
# ErrorMsg <Error Type> <Error Message>
# Displays either a minor (warning) or critical error, exiting on an critical.
if [ "$1" == "ERR" ]; then
        # This is a critical error, game over.
        echo "  ERROR: $2"
        #exit 1
elif [ "$1" == "WRN" ]; then
        # This is only a warning, script continues but may not work fully.
        echo "  WARNING: $2"
fi
}

clear

echo -n "Running a successful command..."
ls 2>/dev/null >1 && echo "Done!" || (echo; ErrorMsg ERR "The command has failed!")

echo

echo -n "Running a failing command..."
ping -w 1 1.0.0.0 >/dev/null && echo "Done!" || (echo; ErrorMsg ERR "The command has failed!")

Last edited by jozyba; 09-09-2007 at 01:44 PM.
 
Old 09-09-2007, 02:38 PM   #7
MS3FGX
LQ Guru
 
Registered: Jan 2004
Location: NJ, USA
Distribution: Slackware, Debian
Posts: 5,852

Original Poster
Rep: Reputation: 361Reputation: 361Reputation: 361Reputation: 361
Quote:
Does this work the way you want it to?
Yes, that is exactly it. I knew I was missing something obvious here. It may not be too elegant, but it definitely works.

Thanks a lot.
 
Old 09-10-2007, 10:15 PM   #8
chrism01
LQ Guru
 
Registered: Aug 2004
Location: Sydney
Distribution: Rocky 9.2
Posts: 18,362

Rep: Reputation: 2751Reputation: 2751Reputation: 2751Reputation: 2751Reputation: 2751Reputation: 2751Reputation: 2751Reputation: 2751Reputation: 2751Reputation: 2751Reputation: 2751
Re your newline issue, we've prob all been there if writing large progs/lots of code.
My (eventually developed) rule is that the msg output fn should do that and no more, in the spirit of the Unix philosophy of KISS and no side-effects/suprises.
It's up to the caller to format the way the msg is laid out.
Of course in C, Perl that's fairly easy...
 
  


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
Bash scripting question re: newlines retrovertigo Programming 4 07-06-2007 09:50 PM
Bash scripting question re: newlines retrovertigo Programming 1 07-06-2007 01:41 AM
Bash: Supress newlines with \c - Doesn't work stefanlasiewski Programming 5 07-26-2005 01:17 PM
Split a string on newlines (bash) rose_bud4201 Programming 7 04-14-2005 01:58 PM
get file contents with newlines into bash variable otoomet Linux - Software 2 01-06-2005 01:23 PM

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

All times are GMT -5. The time now is 02:53 PM.

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