10

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

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

文件.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

4 回答 4

25

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

...
while read line || [[ -n "$line" ]]; do
    ...

编辑:||在while条件中是所谓的短路布尔值——它尝试第一个命令(read line),如果成功,它会跳过第二个([[ -n "$line" ]])并通过循环(基本上,只要read成功,它就像您的原始脚本一样运行)。如果失败,它read会检查第二个命令[[ -n "$line" ]](成功了,循环再运行一次。read$linewhile

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

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

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

于 2013-03-18T21:02:33.247 回答
1

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

如果你 cat 你的文件,你需要看到最后一行成功出现在提示之前。

否则尝试添加:

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

强制文件的最后一行。

于 2013-03-18T19:59:24.513 回答
0

使用grepwhile 循环:

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

使用grep .而不是grep ""将跳过空行。

笔记:

  1. 使用IFS=使任何行缩进保持不变。

  2. 您几乎应该始终将 -r 选项与 read 一起使用。

于 2015-07-14T04:38:20.873 回答
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
于 2016-10-22T13:14:42.633 回答