optivian
optivian

Reputation: 103

Linux "echo -n" not being flushed

I have the following code:

while ...
  echo -n "some text"
done | while read; do
  echo "$REPLY" >> file
done

but echo works only when used without "-n" flag. looks like when using -n, the output is not flushed/read by next while loop

How can I make sure that "some text" will be read even when not followed by EOL?

Upvotes: 9

Views: 928

Answers (4)

Maciej
Maciej

Reputation: 1994

The workaround would be (following original example):

while ...
  echo -n "some text"
done | (cat && echo) | while read; do 
  echo "$REPLY" >> file
done

This will append EOL to the test stream & allow read to read it. The side effect will be an additional EOL at the end of stream.

Upvotes: 1

Walter A
Walter A

Reputation: 20002

You can make read read one char a time, but should add something for reading special characters (newlines, spaces): IFS=.
I want to show that I really capture the characters, so I will uppercase the replies.

i=0
while (( i++<5 )) ; do
  echo -n "some text $i. "
  sleep 1;
done | while IFS= read -rn1 reply; do
  printf "%s" "${reply^^}"
done

This solution has one feature: You will not see any newlines. When you want to see them too, you need to fix this with

i=1
while (( i++<5 )) ; do
  echo -n "some text $i.
second line."
  sleep 1;
done | while IFS= read -rn1 reply; do
  if (( ${#reply} == 0 )); then
     echo
  else
     printf "%s" "${reply^^}"
  fi
done

Upvotes: 0

Uprooted
Uprooted

Reputation: 971

You can't distinguish between

echo -n "some text"

and

echo -n "some t"
echo -n "ext"

so you need some kind of delimiting rule. Usually EOL is used for that. read supports custom delimiter via -d or can split based on number of chars via -n or -N. For example you can make read fire on each symbol:

echo -n qwe | while read -N 1 ch; do echo $ch; done

Upvotes: 4

perreal
perreal

Reputation: 97948

You can start with defining your own delimiter:

while :; do
  echo -n "some text"
  sleep 2
done | while read -d' ' reply; do
  echo "-$reply-"
done

This prints:

-some-
-textsome-
-textsome-

For an email perhaps it makes sense to use . as a delimiter, but you need to decide on some tokenization scheme.

Upvotes: 1

Related Questions