Как подключиться к «нулевому объекту» в bash?

У меня есть следующее:

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.

| без кавычек — это часть синтаксиса конвейера оболочки, а не аргумент первой команды. (Вместо этого обе команды лучше воспринимать как «аргументы» |.)

chepner 02.05.2024 18:01

Насколько я знаю, mysql является интерактивным только тогда и только тогда, когда его стандартным вводом является терминал.

chepner 02.05.2024 18:03

Что здесь означает «интерактивный», например, интерактивный для пользователя? Большинство программ, читающих стандартный ввод, не запускаются в интерактивном режиме, если вы предоставляете что-либо со стандартного ввода.

tjm3772 02.05.2024 18:04
>/dev/stdout имеет мало смысла. /dev/stdout — это просто синоним стандартного вывода, куда по умолчанию осуществляется вывод.
Barmar 02.05.2024 18:05

если вы пытаетесь получить обычное форматирование таблицы вывода, вы можете принудительно это сделать с помощью опции --table.

Barmar 02.05.2024 18:06

Вы можете использовать команду pager в клиенте MySQL. Вам не обязательно устанавливать more или less в качестве пейджера, вы можете использовать любую команду фильтрации. Я часто использую его для grep.

Bill Karwin 02.05.2024 18:22

Это не проблема, о которой вы спрашиваете, но наличие переменной с именем STDOUT, которая иногда не является стандартным выводом, кажется плохой идеей. Может быть, назовите его OUTFD или что-то подобное (но, конечно же, прекратите использовать все имена переменных в верхнем регистре для неэкспортируемых переменных).

Ed Morton 02.05.2024 19:27

@ tjm3772, «интерактивный» означает, что открывается оболочка mysql, в которой можно вводить операторы SQL.

Noel Yap 02.05.2024 19:30

@Barmar, ${STDOUT} может вычислять имя файла в зависимости от параметров скрипта

Noel Yap 02.05.2024 19:31
unix.stackexchange.com/a/406521/133219 может помочь вам вместе с | cat.
Ed Morton 02.05.2024 19:42

@BillKarwin, --pager это отличная идея. К сожалению, документально подтверждено, что он работает только в интерактивном режиме и sed не включен в число допустимых команд.

Noel Yap 02.05.2024 19:44

@Barmar, я пытаюсь вывести файл, который можно использовать с INFILE (который интерпретирует \N как NULL). --table по-прежнему выводит NULL, который необходимо преобразовать в \N

Noel Yap 02.05.2024 19:46

Если вам нужно использовать выходные данные в качестве входных данных для INFILE, вам следует использовать SELECT INTO OUTFILE. Я думаю, что этот вопрос можно считать XY-проблемой.

Bill Karwin 02.05.2024 20:03

@NoelYap Но вы > ${outfile} после подтверждения, что оно равно /dev/stdout. Если вы пытаетесь получить форму CSV с помощью \N, рекомендуем использовать SELECT ... INTO OUTFILE ....

Barmar 02.05.2024 20:57

@Бармар, да, я сделал это целенаправленно и намеренно, чтобы сделать более очевидным сходство и различие между блоками then и блоками else. Вопрос в том, как параметризовать разницу, чтобы можно было вообще исключить if/then/else.

Noel Yap 02.05.2024 22:41

@BillKarwin, SELECT … INTO OUTFILE выведет файл на удаленный компьютер, а не на локальный. См. stackoverflow.com/a/2970539/807037

Noel Yap 02.05.2024 22:43

Вы упомянули, что установка переменной transformer_cmd определенным образом не работает должным образом, но я не вижу этой переменной нигде в вашем коде. Попробуйте создать небольшой воспроизводимый пример, показывающий суть вашего вопроса.

user1934428 03.05.2024 08:59

@user1934428 user1934428, я отредактировал вопрос, чтобы было более понятно, как бы я хотел, чтобы меня использовали transformer_cmd.

Noel Yap 03.05.2024 21:09

Если transformer_cmd должно вести себя как неактивная операция в канале, вы можете установить его в массив, содержащий только слово cat. Одинокий cat просто копирует стандартный ввод в стандартный вывод, не меняя данные.

user1934428 04.05.2024 09:08

@user1934428 user1934428, я попробовал cat как transformer_cmd, но это требование не выполнено. Причина, по которой это не работает, заключается в том, что mysql все равно необходимо открыть интерактивную оболочку для «нулевого объекта» transformer_cmd. Это уже описано в вопросе.

Noel Yap 04.05.2024 16:22
Освоение архитектуры микросервисов с Laravel: Лучшие практики, преимущества и советы для разработчиков
Освоение архитектуры микросервисов с Laravel: Лучшие практики, преимущества и советы для разработчиков
В последние годы архитектура микросервисов приобрела популярность как способ построения масштабируемых и гибких приложений. Laravel , популярный PHP...
Как построить CRUD-приложение в Laravel
Как построить CRUD-приложение в Laravel
Laravel - это популярный PHP-фреймворк, который позволяет быстро и легко создавать веб-приложения. Одной из наиболее распространенных задач в...
Освоение PHP и управление базами данных: Создание собственной СУБД - часть II
Освоение PHP и управление базами данных: Создание собственной СУБД - часть II
В предыдущем посте мы создали функциональность вставки и чтения для нашей динамической СУБД. В этом посте мы собираемся реализовать функции обновления...
Документирование API с помощью Swagger на Springboot
Документирование API с помощью Swagger на Springboot
В предыдущей статье мы уже узнали, как создать Rest API с помощью Springboot и MySql .
Роли и разрешения пользователей без пакета Laravel 9
Роли и разрешения пользователей без пакета Laravel 9
Этот пост изначально был опубликован на techsolutionstuff.com .
Как установить LAMP Stack - Security 5/5 на виртуальную машину Azure Linux VM
Как установить LAMP Stack - Security 5/5 на виртуальную машину Azure Linux VM
В предыдущей статье мы завершили установку базы данных, для тех, кто не знает.
0
20
108
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Подходящего transformer_cmd мне найти не удалось, но по подсказке @chepner получилось следующее:

mysql_cmd "${mysql_args[@]}"

в котором mysql_cmd по умолчанию имеет значение:

function mysql_cmd() {
  mysql "$@"
}

и если бы в скрипте была указана опция, она была бы переопределена на:

function mysql_cmd() {
  mysql "$@" |
    sed -e 's|\\\\|\\|g' |
    tee "${outfile}"
}

Другие вопросы по теме