Для меня, используя virtualenv, export LD_LIBRARY_PATH=/usr/lib/atlas-base/:${LD_LIBRARY_PATH}
в конце моего .bashrc
файла исправил это.
Проблемы, с которыми я столкнулся, устранены. В одном я не уверен. Другой был результатом моего собственного невежества. Что касается странных ошибок компиляции, которые я испытывал с OpenCV 2 и более простой из двух программ, я не уверен. Однако перекомпиляция OpenCV 2, похоже, решила проблему.
Самая большая ошибка, которую я совершил, была связана с make-файлом. Я не знал, что псевдонимы, определенные в.bashrc, не транслируются в make-файлы и что make-файлы имеют совсем другой синтаксис по сравнению с bash. В bash $(opencv2)
вызывает команду, на которую ссылается opencv2, и использует ее вывод в текущей команде. Использование $opencv2
будет ссылаться на переменную и возвращать ее значение. В makefile это не так. На самом деле $(opencv2)
возвращает значение локально определенной переменной с именем opencv2. Команды могут быть определены этими переменными, но должны быть окружены обратными кавычками/метками. Ниже приведен мой исправленный make-файл:
OPENCV=`pkg-config --cflags --libs opencv2`
segmentation : main.cpp Loader.o MeanShift.o ControlParameters.h defs.h
g++ -g main.cpp Loader.o MeanShift.o $(OPENCV) -o segmentation
Loader.o : Loader.cpp Loader.h
g++ -g -c Loader.cpp $(OPENCV)
MeanShift.o : MeanShift.cpp MeanShift.h
g++ -g -c MeanShift.cpp $(OPENCV)
clean:
rm segmentation *.o
Весь скрипт можно сократить до этих двух строк кода (почти, за исключением экспорта некоторых переменных):
printf -v str '%(yr=%Y mo=%-m dy=%-d)T' -1; eval $str # bash 4.2+
printf -v fd '%d%02d%02d' "$yr" "$mo" "$((15*(dy/16)+1))"; echo "$fd"
Или (Дата GNU):
str=$(date +'yr=%Y mo=%-m dy=%-d'); eval $str
fd=$(printf '%d%02d%02d' "$yr" "$mo" "$((15*(dy/16)+1))"); echo "$fd"
Математика для преобразования чисел(dy
)в диапазоне 1..31 в 1 или 16 довольно проста:
(dy>=16)*15 + 1
В C результат true имеет значение 1, тогда 1 умножить на 15 равно 15, плюс 1 равно 16. Если dy больше или равно 16. Более короткая математика (немного сложнее для понимания )— сделать простое целочисленное деление:
(dy/16)*15 + 1
Итак, нам нужно только числоdy
(дня месяца ). Это можно сделать несколькими способами:
printf '%(%-d)T' -1 # in bash 4.2+:
date +'%-d' # in any shell with most date command
Кроме того, значение может быть установлено в переменную с помощью:
printf -v dy '%(%-d)T' -1 # bash (no sub-shell called).
dy=$(date +'%-d') # at the cost of one sub-shell.
Но поскольку нам нужны также год и месяц, мы можем построить одну строку из одного вызова даты, чтобы установить все переменные и оценить строку:
printf -v str '%(yr=%Y mo=%-m dy=%-d)T'; eval $str
В этом случае eval совершенно безопасен, так как не используется пользовательский ввод, а формат строки четко определен, никаких сюрпризов.
Конечно, эквивалент с датой также возможен, но с дополнительными затратами на одну дополнительную оболочку -для захвата вывода date
:
str=$(date +'yr=%Y mo=%-m dy=%-d); eval $str
Вам нужна строка:
printf -v fd '%d%02d%02d' "$yr" "$mo" "$((15*(dy/16)+1))"; echo "$fd"
fd=$(printf '%d%02d%02d' "$yr" "$mo" "$((15*(dy/16)+1))"); echo "$fd"
Просто.
Это сработало, и вот мой код, который сработал:
export day=$(date +%d)
export YR=$(date | awk '{print $6}')
export MM=$(date +%m)
echo $DY
echo "$YR$MM$day"
if [[ $day -ge 16 ]]; then
day=16
else
day=01
fi
printf '%(%Y%m)T%s\n' -1 "$day"
export FD="$YR$MM$day"
echo $FD
dd=$(date +%d)
# values 08 and 09 will not work with arithmetic the way you expect
d=${dd#0} # remove any leading 0
if [ "$d" -ge 16 ] ;then
half=16
else
half=01
fi
date "+%Y%m$half"
Я думаю, что этот код легче всего понять. Единственная сложность связана с использованием арифметических выражений оболочки с числами, начинающимися с цифры 0
, что вы можете не осознавать, если не сталкивались с этим раньше. Строки формата для date
описаны на справочной странице strftime(3)
. Обратите внимание, что существуют реализацииdate
(или printf
), которые не понимают спецификацию преобразования %e
. Конструкция ${dd#0}
описана в справочной страницеbash(1)
(или другой оболочки )в разделе «Расширение параметров».
Вы можете использовать приведенный ниже код для достижения вышеуказанного :#коснитесь mycode.sh
#!/bin/bash
export DD=$(date +%d)
export YYYY=$(date | awk '{print $6}')
export MM=$(date +%m)
echo "$YYYY$MM$DD"
if [[ $DD -eq 16 || $DD -eq 01 ]];then
echo "$DD"
else
echo " The days are not 1st or 16th "
fi
#sh mycode.sh
О/П
20200303
Использование bash
версии 4.2 или выше:
#!/bin/bash
printf -v day '%(%e)T' -1
if [[ $day -lt 16 ]]; then
# 1st half of the month
day=01
else
# 2nd half of the month
day=16
fi
printf '%(%Y%m)T%s\n' -1 "$day"
Первый printf
печатает текущую дату месяца в виде десятичной цифры в переменную day
. Операторы if
ограничивают это либо 01
, либо 16
в зависимости от его значения.
Последнее printf
печатает текущий год и месяц, а затем добавляет в конец строку 01
или 16
.
Аргумент -1
для вызовов printf
заставляет строку формата %(...)T
использовать текущее время в качестве метки времени для форматирования (, если вы используете bash
4.3 или более позднюю версию, это не является строго обязательным для первого вызова так же неявно ).
Более компактная версия дляbash
:
#!/bin/bash
printf -v day '%(%e)T' -1
printf '%(%Y%m)T%.2d\n' -1 "$(( (day < 16) ? 1 : 16 ))"
Здесь я выполняю тест в арифметическом расширении, используя общий тернарный оператор?:
. Это приводит к строке 1
, если $day
меньше 16, и к 16
, если оно больше 16. Результат арифметического расширения затем форматируется в нулевое -заполненное целое число и вставляется после текущего год и месяц.
О вашем коде:
[[... ]]
требует пробелов вокруг [[
и ]]
(, а ;
может стоять сразу после него без пробела, так как это терминатор команды ). date
или любой команды в переменную, используйте подстановку команд:day=$( date +%e )
. Это верно для вашего оператора if
, если он должен был выводить значение (, которого нет ). ECHO
, вероятно, должно быть echo
.%d
выводит заполненное нулем -целое число между 01
и 31
. Обратите внимание, что при использовании такого значения в арифметическом контексте (оператор if
)будет интерпретировать значения от 01
до 07
как восьмеричные значения и будет выдавать ошибки для 08
. ] и09
(это недопустимые восьмеричные числа ). Вот почему я использую %e
вместо этого, чтобы получить целые числа, которые не равны нулю -, заполненные между 1
и 31
. Об этом последнем пункте :я мог бы также использовать
printf -v day '%(%d)T' -1
, чтобы получить нулевые -заполненные значения между 01
и 31
, но тогда мне нужно было бы использовать
if [[ 10#$day -ge 16 ]]; then
, чтобы заставить оболочку интерпретировать строку как десятичное целое, а не как восьмеричное целое.
В качестве скрипта /bin/sh
(также будет работать с bash
версиями до 4.2, т.е. с оболочкой по умолчанию bash
в macOS):
#!/bin/sh
day=$( date +%e )
if [ "$day" -lt 16 ]; then
# 1st half of the month
day=01
else
# 2nd half of the month
day=16
fi
date +"%Y%m$day"
В стандартной оболочке sh
нет строки формата %(...)T
вместо bash
, поэтому мы вынуждены использовать date
для форматирования строки даты. Он также использует [... ]
для тестов, а не [[... ]]
(, и переменные должны быть заключены в двойные кавычки внутри ).
Более компактная версия для/bin/sh
:
#!/bin/sh
day=$( date +%e )
printf '%s%.2d\n' "$(date +%Y%m)" "$(( (day < 16) ? 1 : 16 ))"
Этот более компактный вариант следует из компактного bash
варианта. Единственное отличие состоит в том, что date
используется для форматирования текущего года и месяца.