Bash: Why is echo adding extra space?

2020-03-12 05:02发布

问题:

I get:

$ echo -e "D"{a,b,c}".jpg\n"
Da.jpg
 Db.jpg
 Dc.jpg

Note: The extra spaces before Db and Dc on the 2nd and 3rd line of the output.

Why are these there?

Thanks, Dan

Edit: Since my actual objective had spaces in it (which I should have written originally):

echo -e "Name"{,.}" "{-,}"extra"{,so}" 5v5 "{one,two,No\ four}{,!,\!\!}"\n"

Most solutions here didn't work for me (for loop, xarg, tr). Printf didn't work because of multiple braces expansions that I want to cantesian product.

I combined 3 solutions (mletterle's \b, Dennis Williamson's extra space, and Jim Dennis's using far less quotes) to get:

echo -e "" \\bName{,.}\ {-,}extra{,so}\ 5v5\ {one,two,No\ four}{,\!,\!\!}\\n

Thanks all who answered! I learned a lot from your responses!

Dan

回答1:

The easiest and cleanest solution is to add a backspace to the front of each line:

echo -e -n "\bD"{a,b,c}".jpg\n"

This produces the desired output.



回答2:

use the more portable printf

$ printf "D%s.jpg\n" {a,b,c}
Da.jpg
Db.jpg
Dc.jpg


回答3:

Because that's what brace expansion does. From man bash, under the heading Brace expansion:

Patterns to be brace expanded take the form of an optional preamble, followed by ... a series of comma-separated strings ... followed by an optional postscript. The preamble is prefixed to each string contained within the braces, and the postscript is then appended to each resulting string, expanding left to right For example, a{d,c,b}e expands into ‘ade ace abe’

So in your example, "D" is the preamble and ".jpg\n" is the postscript.

So, after brace expansion occurs, you're left with:

echo -e Da.jpg\n Db.jpg\n Dc.jpg\n

As hewgill points out, the shell then splits this into three tokens and passes them to echo; which outputs each token separated by a space. To get the output you want, you need to use one of the many suggestions here that don't re-inserted the unwanted space between tokens.

It's longer and probably not the neatest way to do this, but the following gives the output you're after:

for file in "D"{a,b,c}".jpg"
do
  echo ${file}
done


回答4:

echo always adds spaces between arguments. Try your command without \n and compare the results.



回答5:

You can get the desired effect by using xargs to separate the arguments spit by the first echo into a line each:

$ echo "D"{a,b,c}".jpg" | xargs -n1 echo
Da.jpg
Db.jpg
Dc.jpg


回答6:

You can get a more consistent look by prepending a null:

$ echo -en "" "D"{a..c}".jpg\n"
 Da.jpg
 Db.jpg
 Dc.jpg

Now they all have an extra space. Also, using -n eliminates the extra newline at the end. Also, you can use a range in your brace expansion.



回答7:

Here is a solution using sed (that builds upon https://stackoverflow.com/a/2003856/8180143):

$ echo -en "" "D"{a..c}".jpg\n" | sed 's/ //'
Da.jpg
Db.jpg
Dc.jpg

This solution has the advantage of working with inputs having spaces, e.g.,

$ echo -en "" "D "{a..c}".jpg\n" | sed 's/ //'
D a.jpg
D b.jpg
D c.jpg


标签: bash syntax echo