Looping through the content of a file in Bash

后端 未结 13 2383
傲寒
傲寒 2020-11-21 10:08

How do I iterate through each line of a text file with Bash?

With this script:

echo \"Start!\"
for p in (peptides.txt)
do
    echo \"${p}\"
done
         


        
13条回答
  •  栀梦
    栀梦 (楼主)
    2020-11-21 10:37

    Suppose you have this file:

    $ cat /tmp/test.txt
    Line 1
        Line 2 has leading space
    Line 3 followed by blank line
    
    Line 5 (follows a blank line) and has trailing space    
    Line 6 has no ending CR
    

    There are four elements that will alter the meaning of the file output read by many Bash solutions:

    1. The blank line 4;
    2. Leading or trailing spaces on two lines;
    3. Maintaining the meaning of individual lines (i.e., each line is a record);
    4. The line 6 not terminated with a CR.

    If you want the text file line by line including blank lines and terminating lines without CR, you must use a while loop and you must have an alternate test for the final line.

    Here are the methods that may change the file (in comparison to what cat returns):

    1) Lose the last line and leading and trailing spaces:

    $ while read -r p; do printf "%s\n" "'$p'"; done 

    (If you do while IFS= read -r p; do printf "%s\n" "'$p'"; done instead, you preserve the leading and trailing spaces but still lose the last line if it is not terminated with CR)

    2) Using process substitution with cat will reads the entire file in one gulp and loses the meaning of individual lines:

    $ for p in "$(cat /tmp/test.txt)"; do printf "%s\n" "'$p'"; done
    'Line 1
        Line 2 has leading space
    Line 3 followed by blank line
    
    Line 5 (follows a blank line) and has trailing space    
    Line 6 has no ending CR'
    

    (If you remove the " from $(cat /tmp/test.txt) you read the file word by word rather than one gulp. Also probably not what is intended...)


    The most robust and simplest way to read a file line-by-line and preserve all spacing is:

    $ while IFS= read -r line || [[ -n $line ]]; do printf "'%s'\n" "$line"; done 

    If you want to strip leading and trading spaces, remove the IFS= part:

    $ while read -r line || [[ -n $line ]]; do printf "'%s'\n" "$line"; done 

    (A text file without a terminating \n, while fairly common, is considered broken under POSIX. If you can count on the trailing \n you do not need || [[ -n $line ]] in the while loop.)

    More at the BASH FAQ

提交回复
热议问题