У меня есть следующее:
if [[ "${outfile}" == '/dev/stdout' ]]; then
"${mysql_cmd[@]}" <"${infile}" >"${outfile}"
else
"${mysql_cmd[@]}" <"${infile}" |
sed -e 's|[[:<:]]NULL[[:>:]]|\\N|g' >"${outfile}"
fi
sed
предназначен для преобразования NULL
в \N
, чтобы результат можно было использовать с LOAD DATA LOCAL INFILE
.
Я хотел бы превратить его в однострочник, похожий на:
"${mysql_cmd[@]}" <"${infile}" | "${transformer_cmd[@]}" >"${outfile}"
Когда transformer_cmd
является «нулевым объектом» (т. е. не является командой sed
), mysql
должен продолжать оставаться интерактивным (таким образом, чтобы открывалась оболочка mysql
, в которую можно вводить операторы SQL). Я попробовал cat
как transformer_cmd
, но это требование не выполнено.
Это возможно? Если да, то как?
Я бы предпочел не делать что-то вроде "${mysql_cmd[@]}" <"${infile}" "${transformer_cmd}" >"${outfile}"
, чтобы transformer_cmd
включало |
, но сделаю это, если нет другого способа.
ДОПОЛНЕНИЕ: transformer_cmd
включение |
не работает, поскольку по какой-то причине ${transformer_cmd}
(без двойных кавычек) все еще интерпретируется как аргумент mysql
.
Насколько я знаю, mysql
является интерактивным только тогда и только тогда, когда его стандартным вводом является терминал.
Что здесь означает «интерактивный», например, интерактивный для пользователя? Большинство программ, читающих стандартный ввод, не запускаются в интерактивном режиме, если вы предоставляете что-либо со стандартного ввода.
>/dev/stdout
имеет мало смысла. /dev/stdout
— это просто синоним стандартного вывода, куда по умолчанию осуществляется вывод.
если вы пытаетесь получить обычное форматирование таблицы вывода, вы можете принудительно это сделать с помощью опции --table
.
Вы можете использовать команду pager
в клиенте MySQL. Вам не обязательно устанавливать more
или less
в качестве пейджера, вы можете использовать любую команду фильтрации. Я часто использую его для grep
.
Это не проблема, о которой вы спрашиваете, но наличие переменной с именем STDOUT
, которая иногда не является стандартным выводом, кажется плохой идеей. Может быть, назовите его OUTFD
или что-то подобное (но, конечно же, прекратите использовать все имена переменных в верхнем регистре для неэкспортируемых переменных).
@ tjm3772, «интерактивный» означает, что открывается оболочка mysql
, в которой можно вводить операторы SQL.
@Barmar, ${STDOUT}
может вычислять имя файла в зависимости от параметров скрипта
@BillKarwin, --pager
это отличная идея. К сожалению, документально подтверждено, что он работает только в интерактивном режиме и sed
не включен в число допустимых команд.
@Barmar, я пытаюсь вывести файл, который можно использовать с INFILE
(который интерпретирует \N
как NULL
). --table
по-прежнему выводит NULL
, который необходимо преобразовать в \N
Если вам нужно использовать выходные данные в качестве входных данных для INFILE
, вам следует использовать SELECT INTO OUTFILE
. Я думаю, что этот вопрос можно считать XY-проблемой.
@NoelYap Но вы > ${outfile}
после подтверждения, что оно равно /dev/stdout
. Если вы пытаетесь получить форму CSV с помощью \N
, рекомендуем использовать SELECT ... INTO OUTFILE ...
.
@Бармар, да, я сделал это целенаправленно и намеренно, чтобы сделать более очевидным сходство и различие между блоками then
и блоками else
. Вопрос в том, как параметризовать разницу, чтобы можно было вообще исключить if
/then
/else
.
@BillKarwin, SELECT … INTO OUTFILE
выведет файл на удаленный компьютер, а не на локальный. См. stackoverflow.com/a/2970539/807037
Вы упомянули, что установка переменной transformer_cmd
определенным образом не работает должным образом, но я не вижу этой переменной нигде в вашем коде. Попробуйте создать небольшой воспроизводимый пример, показывающий суть вашего вопроса.
@user1934428 user1934428, я отредактировал вопрос, чтобы было более понятно, как бы я хотел, чтобы меня использовали transformer_cmd
.
Если transformer_cmd
должно вести себя как неактивная операция в канале, вы можете установить его в массив, содержащий только слово cat
. Одинокий cat
просто копирует стандартный ввод в стандартный вывод, не меняя данные.
@user1934428 user1934428, я попробовал cat
как transformer_cmd
, но это требование не выполнено. Причина, по которой это не работает, заключается в том, что mysql
все равно необходимо открыть интерактивную оболочку для «нулевого объекта» transformer_cmd
. Это уже описано в вопросе.
Подходящего transformer_cmd
мне найти не удалось, но по подсказке @chepner получилось следующее:
mysql_cmd "${mysql_args[@]}"
в котором mysql_cmd
по умолчанию имеет значение:
function mysql_cmd() {
mysql "$@"
}
и если бы в скрипте была указана опция, она была бы переопределена на:
function mysql_cmd() {
mysql "$@" |
sed -e 's|\\\\|\\|g' |
tee "${outfile}"
}
|
без кавычек — это часть синтаксиса конвейера оболочки, а не аргумент первой команды. (Вместо этого обе команды лучше воспринимать как «аргументы»|
.)