Чтение последней строки файла в скрипте bash при чтении файла строка за строкой
Я пишу сценарий для чтения команд из файла и выполнения определенной команды. Я хочу, чтобы мой скрипт работал либо для одного входного аргумента, либо когда аргумент является именем файла, содержащим рассматриваемые аргументы.
мой код ниже работает, за исключением одной проблемы, он игнорирует последнюю строку файла. Итак, если файл был следующим.
.txtfile1
file2
сценарий размещена ниже работает только команда файл.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 ответов
похоже, что в вашем входном файле отсутствует символ новой строки после последней строки. Когда read
встречи-это переменная ($line
в этом случае) до последней строки, но затем возвращает ошибку конца файла, поэтому цикл не выполняется для этой последней строки. Чтобы обойти это, вы можете выполнить цикл, если read
успешно или он читал что-нибудь в $line
:
...
while read line || [[ -n "$line" ]]; do
...
"правка":||
в то время как состояние, что известно как короткое замыкание boolean -- он пытается выполнить первую команду (read line
), и если это удастся, он пропускает второй ([[ -n "$line" ]]
) и проходит через цикл (в основном, до тех пор, пока read
успешно, он работает так же, как ваш оригинальный скрипт). Если read
не удается, он проверяет вторую команду ([[ -n "$line" ]]
) -- if read
читать ничего $line
прежде чем попасть в конец файла (т. е. если в файле была unterminated последняя строка), это будет успешным, поэтому while
условие в целом считается получилось, и петля проходит еще раз.
после последней незаконченной обработки, он снова выполните тест. На этот раз read
произойдет сбой (он все еще находится в конце файла), и так как read
ничего не читал в $line
в этот раз .
обратите внимание, что условное выражение в [[ ... ]]
тонко отличается от тестовой команды [ ... ]
- см. BashFAQ #031 для различий и a список доступных тестов. И они оба отличаются от арифметического выражения с (( ... ))
, и полностью отличается от подуровень с( ... )
...
ваша проблема, кажется, отсутствует возврат каретки в вашем файле.
Если вы cat ваш файл, вы должны увидеть последнюю строку успешно появляется перед promopt.
в противном случае попробуйте добавить :
echo "Reading "$currentJob
echo >> $currentJob #add new line
while read line; do
в силу последней строке файла.
используя grep
с циклом while:
while IFS= read -r line; do
echo "$line"
done < <(grep "" file)
используя grep .
вместо grep ""
пропустит пустые строки.
Примечание:
используя
IFS=
сохраняет любой отступ линии нетронутым.
Я нашел код, который читает файл, включая последнюю строку, и работает без команды [[]]:
DONE=false
until $DONE; do
read s || DONE=true
# you code
done < FILE