Jimothy
Jimothy

Reputation: 9730

Blank lines in zsh loop

Running a loop in zsh like the one below gives blank lines in the output (ignore the triviality of this loop; it's just an example. A more realistic example might be running mysql -s -e "show databases;" and doing something for each database).

for foo in $(cat test.txt); do
    echo $foo
done



alpha
bravo
charlie
delta

In this example, if test.txt has four lines, three blank lines appear. If it had five lines, four blank lines would appear. In my MySql example, there would be one fewer blank lines than there are MySql databases.

What is causing these blank lines, and how can I prevent them? Running the same script in Bash doesn't give the blank lines.


Edit: It appears the Oh My Zsh is the culprit, though I haven't yet figured out why. If I comment out source $ZSH/oh-my-zsh.sh in .zshrc, the blank lines no longer appear.

Upvotes: 2

Views: 1715

Answers (2)

indythegeek
indythegeek

Reputation: 46

So yes, ~/.oh-my-zsh is the culprit. Going into ~/.oh-my-zsh/lib/termsupport.zsh

#Appears at the beginning of (and during) of command execution
function omz_termsupport_preexec {
  emulate -L zsh
  setopt extended_glob
  local CMD=${1[(wr)^(*=*|sudo|ssh|rake|-*)]} #cmd name only, or if this is sudo or ssh, the next cmd
  local LINE="${2:gs/$/\\$}"
  LINE="${LINE:gs/%/%%}"
  title "$CMD" "%100>...>$LINE%<<"
}

We see that it attempts to set the title to the whole command including the things that come after the command, lopping off prefixes like sudo and doing some escaping of characters like $ and %. But for some reason, when you do a cat, it throws in some newlines. For a quick fix, I'm hobbling oh-my-zsh a bit by just setting the title to $CMD, like so:

#Appears at the beginning of (and during) of command execution
function omz_termsupport_preexec {
  emulate -L zsh
  setopt extended_glob
  local CMD=${1[(wr)^(*=*|sudo|ssh|rake|-*)]} #cmd name only, or if this is sudo or ssh, the next cmd
  ## Removing command argument parsing because of cat bug
  #local LINE="${2:gs/$/\\$}"
  #LINE="${LINE:gs/%/%%}"
  #title "$CMD" "%100>...>$LINE%<<"
  title "$CMD" 
}

I've gone back through the recent-ish history of this file on oh-my-zsh's github, but it appears this bug has been there for some time. The "right" answer is probably to do some nested expansion around $LINE that removes blank and newlines and make a pull request to oh-my-zsh. But my zsh foo is still too weak for this.

Upvotes: 3

Wolph
Wolph

Reputation: 80031

I would assume that Bash is somehow filtering out the whitespace completely. An easy fix for this is to grep a little.

Example:

for foo in $(grep -v '^$' test.txt); do
    # The quotes are recommended to make sure you shell won't do weird things with the variables
    echo "$foo"
done

Upvotes: -1

Related Questions