0

I'm getting some weird behaviour from a for loop that reads each line in a file and after each line, reads every word. Read skips the last word on each line. I think I may have to specify that both whitespace and newline are deliminator but I haven't found out how to do that. Here is the part of the script that matters:

  cat $i | while read line    
    do
        echo $line
        sleep 1
        #Process each word
        echo $line | while read -d ' '  word
        do
            echo $word
            sleep 1
        done
    done
Asgeir
  • 727
  • 3
  • 9
  • 20

4 Answers4

2

Did you see How to split one string into multiple strings separated by at least one space in bash shell?? maybe you could just do:

for word in $line
do
    echo $word
    sleep 1
done
Community
  • 1
  • 1
  • That seems to work like a charm, guess I was too hung up on using read since I use it to read the file. – Asgeir Feb 25 '12 at 18:36
  • Not sure, but I think this will subject $line to the usual shell expansions, which might turn out to be more than you want. You'll want to experiment with what happens with input lines containing double- and single-quotes and backticks (balanced and unbalanced), and dollar-signs (`$`). If this turns out to be a problem for you, you might consider the solution based around `fmt` which I suggest below. – Dale Hagglund Feb 25 '12 at 19:00
2

The syntax of the for command is:

      for name [ [in [words ...] ] ; ] do commands; done

Expand words, and execute commands once for each member in the resultant list, with name bound to the current member.

cat $i | while read line    
do
    echo $line
    sleep 1
    #Process each word
    for word in $line
    do
        echo $word
        sleep 1
    done
done
kev
  • 155,172
  • 47
  • 273
  • 272
  • That seems to work like a charm, guess I was too hung up on using read since I use it to read the file – Asgeir Feb 25 '12 at 18:36
0

Try using the cut command instead of read -d

0

If you don't need to remember the line boundaries, the fmt command can be useful. fmt reflows plain text on stdin into given maximum line length, and so if you give it a max line length of one, it ends up splitting each word of the input onto its own line. For your problems, perhaps

cat $1 |
fmt -1 |
while read word
do
    # do something with $word
end

Note that you've lost all original line boundaries here, and you're dependent on fmt's definition of what a word is. If you really need the line boundaries for some reason, you could think about something like

cat $1 |
while read line
do
    # do something with $line
    echo "$line" | 
    fmt -1 |
    while read word
    do
        # do something with $word
    done
done
Dale Hagglund
  • 16,074
  • 4
  • 30
  • 37