我正在编写一个脚本来读取文件中的命令并执行特定命令。我希望我的脚本适用于单个输入参数,或者当参数是包含相关参数的文件名时。
我的下面的代码除了一个问题外无效,它忽略了文件的最后一行。所以,如果文件如下。
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
答案 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 ""
将跳过空行。
注意:
使用IFS=
可以保持任何行缩进。
答案 3 :(得分:0)
我发现一些代码读取包含最后一行的文件,并且在没有[[]]命令的情况下工作:
DONE=false
until $DONE; do
read s || DONE=true
# you code
done < FILE