LinuxQuestions.org
Support LQ: Use code LQ3 and save $3 on Domain Registration
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 11-25-2012, 08:18 AM   #1
killout
LQ Newbie
 
Registered: Nov 2012
Posts: 14

Rep: Reputation: Disabled
Bash: prevent read to remove spaces


Hello, linuxquestions.

I have reading "Unix and Linux adminitration handbook", and faced with a problem:

I have command:
Code:
alex@just ~ $ echo one two; echo three          four   |  while read -e "fname"; do echo ${fname} ; done 
one two
three four
Why the is only one space betweeen "three" and "four" in the output? How can i prevent this?
 
Old 11-25-2012, 08:54 AM   #2
pixellany
LQ Veteran
 
Registered: Nov 2005
Location: Annapolis, MD
Distribution: Arch/XFCE
Posts: 17,802

Rep: Reputation: 738Reputation: 738Reputation: 738Reputation: 738Reputation: 738Reputation: 738Reputation: 738
Here's a hint:
Code:
[mherring@herring_lap play]$ echo $var
three four
[mherring@herring_lap play]$ echo "$var"
three    four
 
1 members found this post helpful.
Old 11-25-2012, 09:12 AM   #3
shivaa
Senior Member
 
Registered: Jul 2012
Location: Grenoble, Fr.
Distribution: Sun Solaris, RHEL, Ubuntu, Debian 6.0
Posts: 1,800
Blog Entries: 4

Rep: Reputation: 286Reputation: 286Reputation: 286
You can print multiple space(s) using \n or tab(s) using \t, as:
Code:
echo -e "three\nfour"  # For one space
echo -e "three\n\nfour"  # For two spaces
echo -e "three\tfour"  # For one tab space
echo -e "three\t\tfour"  # For two tab space and so on...
Output:
Code:
three four
three  four
three     four
three          four

Last edited by shivaa; 11-25-2012 at 09:14 AM.
 
Old 11-25-2012, 10:08 AM   #4
killout
LQ Newbie
 
Registered: Nov 2012
Posts: 14

Original Poster
Rep: Reputation: Disabled
Quote:
Originally Posted by shivaa View Post
You can print multiple space(s) using \n or tab(s) using \t, as:
Code:
echo -e "three\nfour"  # For one space
echo -e "three\n\nfour"  # For two spaces
echo -e "three\tfour"  # For one tab space
echo -e "three\t\tfour"  # For two tab space and so on...
Output:
Code:
three four
three  four
three     four
three          four
Shivaa, thank you for your advice, but i can't apply it because task is rename files with using "find", pipe it to "while read fname" commands.
 
Old 11-25-2012, 10:09 AM   #5
killout
LQ Newbie
 
Registered: Nov 2012
Posts: 14

Original Poster
Rep: Reputation: Disabled
Quote:
Originally Posted by pixellany View Post
Here's a hint:
Code:
[mherring@herring_lap play]$ echo $var
three four
[mherring@herring_lap play]$ echo "$var"
three    four
pixellany, thank you! Your ancwer helps me:

Code:
alex@just ~ $ echo "one two"; echo "three          four"   |  while read fname; do echo "$fname" ; done
one two
three          four
 
Old 11-25-2012, 11:13 AM   #6
David the H.
Bash Guru
 
Registered: Jun 2004
Location: Osaka, Japan
Distribution: Debian sid + kde 3.5 & 4.4
Posts: 6,823

Rep: Reputation: 1957Reputation: 1957Reputation: 1957Reputation: 1957Reputation: 1957Reputation: 1957Reputation: 1957Reputation: 1957Reputation: 1957Reputation: 1957Reputation: 1957
It's vital in scripting to understand how the shell handles arguments and whitespace. Study these links for the details:

http://mywiki.wooledge.org/Arguments
http://mywiki.wooledge.org/WordSplitting
http://mywiki.wooledge.org/Quotes

The function of the echo command is to print each and every argument it gets separately, with a single space between them. Since your text strings are unquoted the shell breaks the them up into their individual words before echo processes them.

Next, if we look closely at your original scriptlet:

Code:
$ echo one two; echo three          four   |  while read -e "fname"; do echo ${fname} ; done 
one two
three four
The semicolon between the two echos means you are running two separate commands. The first echo executes and prints "one two" to stdout, then the second echo executes, sending its output into the while loop, which prints it with the third echo. So only "three four" is actually processed by the loop. This can be avoided with command grouping, or through the use of "echo -e" to combine them into a single command, as pointed out by shivaa.


Next, you should be aware of the variable scoping limitation when using pipes. The above will work as long as you are only echoing the results, but it wouldn't work if you needed to set variables that are still needed after the loop terminates.

The recommended bash syntax is to instead feed the loop with a process substitution or a here doc/here string.

Code:
while read -r fname; do
	echo "$fname"
done < <( echo -e 'one two\nthree          four' )

while read -r fname; do
	echo "$fname"
done <<<$'one two\nthree          four'
As mentioned in the quoting page I gave above, the special $'..' quoting pattern acts similarly to echo -e, expanding backslash characters.

The -e option to read is also superfluous if you aren't using it interactively, BTW. But it is recommended to always use the -r option, particularly if the input text can contain literal backslashes.


Finally, be aware that printf is often a better choice when you simply need to output your data on multiple lines, since it has implicit looping built into it.

Code:
printf '%s\n' 'one two' 'three          four'

Last edited by David the H.; 11-25-2012 at 11:15 AM. Reason: stupid double posting bug
 
1 members found this post helpful.
Old 11-29-2012, 03:03 PM   #7
killout
LQ Newbie
 
Registered: Nov 2012
Posts: 14

Original Poster
Rep: Reputation: Disabled
David the H., thanks for such a detailed response!
I will study links,that you have posted.
 
Old 11-30-2012, 06:46 AM   #8
David the H.
Bash Guru
 
Registered: Jun 2004
Location: Osaka, Japan
Distribution: Debian sid + kde 3.5 & 4.4
Posts: 6,823

Rep: Reputation: 1957Reputation: 1957Reputation: 1957Reputation: 1957Reputation: 1957Reputation: 1957Reputation: 1957Reputation: 1957Reputation: 1957Reputation: 1957Reputation: 1957
Glad to help out.

I should probably also have included BashFAQ #1, which is all about how to properly read lines of text input.

When you get a chance, also take the time to read through the whole BashGuide from the same site. It provides an excellent overview of all the basics you should know for good scripting. Then round it off with the BashPitfalls, to help you avoid common errors.
 
1 members found this post helpful.
  


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: remove leading spaces with only expansions romagnolo Linux - General 15 02-13-2012 07:39 AM
Bash - to remove files with spaces in name iwitham Programming 4 01-23-2012 01:52 PM
Bash Command to Remove Spaces CincinnatiKid Linux - General 16 09-18-2010 10:46 AM
Bash script to remove capitalisation and spaces form a filename scuzzman Programming 11 05-18-2008 01:28 PM


All times are GMT -5. The time now is 11: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
Facebook: linuxquestions Google+: linuxquestions
Open Source Consulting | Domain Registration