Проблемы с одинарными кавычками в команде с выполнением SQL-запроса в bash-скрипте

Вопрос или проблема

Я пытаюсь запустить следующую команду, которая работает без проблем при запуске в терминале:

ogr2ogr -append -f PostgreSQL "PG:host=$PGHOST dbname=$PGDBNAME user=$PGUSER password=$PGPASS" \
--config OGR_TRUNCATE=YES "$FILENAME" -nln "${PGTABLEPREFIX}${PGTABLENAME}" \
-sql "SELECT * FROM elements WHERE OGR_GEOMETRY IN ('LINESTRING','MULTILINESTRING','LINE')" \
-s_srs EPSG:5514 -t_srs EPSG:4326 -nlt CONVERT_TO_LINEAR -nlt PROMOTE_TO_MULTI

Когда эта команда включена в состав bash-скрипта, возникает проблема с секцией SQL-запроса, которая интерпретируется неправильно следующим образом:

ogr2ogr -append -f PostgreSQL 'PG:host=xxx.xxx.xxx.xxx dbname=xxx user=gis password=xxxxxx' \
--config OGR_TRUNCATE=YES test.dgn -nln layer-test \
-sql 'SELECT * FROM elements WHERE OGR_GEOMETRY IN ('\''LINESTRING'\'','\''MULTILINESTRING'\'','\''LINE'\'')' \
-s_srs EPSG:5514 -t_srs EPSG:4326 -nlt CONVERT_TO_LINEAR -nlt PROMOTE_TO_MULTI

Я пробовал:

  • -sql $'SELECT * FROM elements WHERE OGR_GEOMETRY IN (\'LINESTRING\', \'MULTILINESTRING\', \'LINE\')'
  • создать всю команду в переменной и выполнить её с помощью eval
  • больше комбинаций одинарных и двойных кавычек

Все с более или менее одинаковыми результатами. Как я могу сделать это правильно?

Ответ или решение

Проблема, с которой вы столкнулись, связана с неправильной интерпретацией одинарных кавычек в вашем SQL-запросе при запуске команды ogr2ogr из Bash-скрипта. Когда вы используете одинарные кавычки, Bash интерпретирует содержимое буквально, и это может вызвать ошибки в SQL-запросе, так как внутри одинарных кавычек нельзя использовать другой символ одинарной кавычки. Давайте рассмотрим это более подробно и предложим решение.

Проблема с одинарными кавычками

Когда вы пишете ваш SQL-запрос следующим образом:

sql_query='SELECT * FROM elements WHERE OGR_GEOMETRY IN ('LINESTRING','MULTILINESTRING','LINE')'

Bash не сможет правильно понять вложенные одинарные кавычки. Это приводит к ошибкам при выполнении команды, так как в этом случае Bash ожидает закрытие кавычек.

Рекомендации по решению

Ваша цель — правильно экранировать одиночные кавычки или использовать различные конструкторы строк, чтобы избежать путаницы. Вот несколько подходов, которые могут помочь:

1. Использование двойных кавычек с экранированием

Вы можете использовать двойные кавычки для создания строки и экранировать одинарные кавычки внутри:

sql_query="SELECT * FROM elements WHERE OGR_GEOMETRY IN ('LINESTRING', 'MULTILINESTRING', 'LINE')"

Этот подход позволяет указывать строки внутри одинарных кавычек без необходимости экранирования.

2. Использование конструкции $'...' для экранирования

В Bash также есть возможность использовать специальный синтаксис $'...', который позволяет использовать экранирование внутри строки:

sql_query=$'SELECT * FROM elements WHERE OGR_GEOMETRY IN (\'LINESTRING\', \'MULTILINESTRING\', \'LINE\')'

Этот вариант также будет работать и позволит разместить одинарные кавычки без конфликтов.

3. Построение команды в виде переменной

Вы можете собрать всю команду в одной переменной и выполнить ее с помощью eval, однако это может быть менее безопасно и рекомендуется использовать с осторожностью:

command="ogr2ogr -append -f PostgreSQL \"PG:host=$PGHOST dbname=$PGDBNAME user=$PGUSER password=$PGPASS\" \
--config OGR_TRUNCATE=YES \"$FILENAME\" -nln \"${PGTABLEPREFIX}${PGTABLENAME}\" \
-sql \"$sql_query\" -s_srs EPSG:5514 -t_srs EPSG:4326 -nlt CONVERT_TO_LINEAR -nlt PROMOTE_TO_MULTI"
eval "$command"

4. Использование массива в Bash

Если ваш скрипт становится слишком сложным или длинным, использование массивов может значительно упростить составление команды:

command=(ogr2ogr -append -f PostgreSQL "PG:host=$PGHOST dbname=$PGDBNAME user=$PGUSER password=$PGPASS" \
--config OGR_TRUNCATE=YES "$FILENAME" -nln "${PGTABLEPREFIX}${PGTABLENAME}" \
-sql "SELECT * FROM elements WHERE OGR_GEOMETRY IN ('LINESTRING', 'MULTILINESTRING', 'LINE')" \
-s_srs EPSG:5514 -t_srs EPSG:4326 -nlt CONVERT_TO_LINEAR -nlt PROMOTE_TO_MULTI)

"${command[@]}"

Этот метод позволяет избежать потенциальных конфликтов со специальными символами и улучшает читаемость скрипта.

Заключение

Ваша проблема с одинарными кавычками в SQL-запросе в Bash-скрипте может быть решена с помощью правильного подхода к экранированию и построению строк. Рекомендуем использовать двойные кавычки или конструкцию с $'...', а также рассмотреть возможность построения команды в виде массива для лучшей читаемости и удобства. Применяя эти методы, вы сможете избежать распространенных ошибок и упростить процесс работы вашего скрипта.

Оцените материал
Добавить комментарий

Капча загружается...