逐行读取文件时读取bash脚本中的最后一行文件

时间:2013-03-18 19:46:55

标签: bash

我正在编写一个脚本来读取文件中的命令并执行特定命令。我希望我的脚本适用于单个输入参数,或者当参数是包含相关参数的文件名时。

我的下面的代码除了一个问题外无效,它忽略了文件的最后一行。所以,如果文件如下。

file.txt的

file1
file2

下面发布的脚本只运行file.txt的命令

for currentJob in "$@"
do
    if [[ "$currentJob" != *.* ]]  #single file input arg
    then
        echo $currentJob
        serverJobName="$( tr '[A-Z]' '[a-z]' <<< "$currentJob" )"  #Change to lowercase
                                                                   #run cURL job
        curl -o "$currentJob"PisaInterfaces.xml http://www.ebi.ac.uk/msd-srv/pisa/cgi-bin/interfaces.pisa?"$serverJobName"
    else  #file with list of pdbs
        echo "Reading "$currentJob
        while read line; do
            echo "-"$line
            serverJobName="$( tr '[A-Z]' '[a-z]' <<< "$line" )"
            curl -o "$line"PisaInterfaces.xml http://www.ebi.ac.uk/msd-srv/pisa/cgi-bin/interfaces.pisa?"$serverJobName"
        done < "$currentJob"
    fi
done

当然,有一个显而易见的工作,在while循环后我重复循环内部的步骤以完成最后一个文件的命令,但这是不可取的,因为我在while循环中所做的任何更改都必须在while循环之外再次重复。我在网上搜索过,找不到有人问这个确切的问题。我确信它在那里,但我还没有找到它。

我得到的输出如下。

>testScript.sh file.txt
Reading file.txt
-file1
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100  642k    0  642k    0     0   349k      0 --:--:--  0:00:01 --:--:--  492k

我的bash版本是3.2.48

4 个答案:

答案 0 :(得分:24)

听起来你的输入文件在最后一行之后缺少换行符。当read遇到此情况时,它会将变量(在这种情况下为$line)设置为最后一行,但随后会返回文件结束错误,因此循环不会针对最后一行执行。要解决此问题,您可以在read成功将任何内容读入$line时执行循环:

...
while read line || [[ -n "$line" ]]; do
    ...
编辑:while条件中的||是所谓的短路布尔值 - 它尝试第一个命令(read line),如果成功则跳过第二个命令({{ 1}})并完成循环(基本上,只要[[ -n "$line" ]]成功,它就像你的原始脚本一样运行)。如果read失败,它会检查第二个命令(read) - 如果[[ -n "$line" ]]在到达文件末尾之前将任何内容读入read(即如果有未终止的话)文件中的最后一行),这将成功,因此整个$line条件被认为已成功,循环再次运行。

在处理完最后一条未终止的行之后,它将再次运行测试。这一次,while将失败(它仍然在文件的末尾),并且由于read未在read中读取任何内容,因此$line测试将< em>也失败,因此整个[[ -n "$line" ]]条件失败并且循环终止。

EDIT2:while是一个bash条件表达式 - 它不是常规命令,但它可以用来代替一个。它的主要目的是根据其中的条件成功或失败。在这种情况下,[[ ]]测试意味着如果操作数(-n)是NONempty则成功。有一个其他测试条件here的列表,以及"$line"命令的手册页。

请注意test中的条件表达式与测试命令[[ ... ]]略有不同 - 请参阅BashFAQ #031了解差异和可用测试列表。它们与[ ... ]的算术表达式不同,与(( ... ))的子shell完全不同......

答案 1 :(得分:1)

您的问题似乎是文件中缺少回车。

如果您捕获文件,则需要在promopt之前看到最后一行成功出现。

否则尝试添加:

    echo "Reading "$currentJob
    echo >> $currentJob #add new line
    while read line; do

强制文件的最后一行。

答案 2 :(得分:0)

grep与while循环一起使用:

while IFS= read -r line; do
  echo "$line"
done < <(grep "" file)

使用grep .代替grep ""将跳过空行。

注意:

  1. 使用IFS=可以保持任何行缩进。

  2. You should almost always use the -r option with read.

答案 3 :(得分:0)

我发现一些代码读取包含最后一行的文件,并且在没有[[]]命令的情况下工作:

http://www.unix.com/shell-programming-and-scripting/161645-read-file-using-while-loop-not-reading-last-line.html

DONE=false
until $DONE; do
    read s || DONE=true
    # you code
done < FILE