LINUX.ORG.RU

Bash и переменные с пробелами

 


0

1
> export SYSLIBPATHS="-L/Haiku 64 (USB)/home/Tests/MinApp (riscv64)/sdk-riscv64/lib"
> clang "${SYSLIBPATHS}"
clang-9: error: no input files

> clang ${SYSLIBPATHS}
clang-9: error: no such file or directory: '64'
clang-9: error: no such file or directory: '(USB)/home/Tests/MinApp'
clang-9: error: no such file or directory: '(riscv64)/sdk-riscv64/lib'
clang-9: error: no input files

> export SYSLIBPATHS="\"-L/Haiku 64 (USB)/home/Tests/MinApp (riscv64)/sdk-riscv64/lib\""
> clang ${SYSLIBPATHS}
clang-9: error: no such file or directory: '"-L/Haiku'
clang-9: error: no such file or directory: '64'
clang-9: error: no such file or directory: '(USB)/home/Tests/MinApp'
clang-9: error: no such file or directory: '(riscv64)/sdk-riscv64/lib"'
clang-9: error: no input files

> clang "-L/Haiku 64 (USB)/home/Tests/MinApp (riscv64)/sdk-riscv64/lib"
clang-9: error: no input files

Почему строка в кавычках внутри переменной не работает и как сделать чтобы работало?

★★★★★

Самый первый вариант и есть правильный. Зачем ты пытаешься скормить буквальный путь с кавычкой в компилятор? Его заведомо нет на диске.

d_a ★★★★★
()
Ответ на: комментарий от d_a

Самый первый вариант и есть правильный.

А что делать если в SYSLIBPATHS несколько путей?

X512 ★★★★★
() автор топика
Ответ на: комментарий от aol

заэкранировать пробелы?

> export SYSLIBPATHS="-L/Haiku\ 64\ \(USB\)/home/Tests/MinApp\ \(riscv64\)/sdk-riscv64/lib"
> clang ${SYSLIBPATHS}
clang-9: error: no such file or directory: '64\'
clang-9: error: no such file or directory: '\(USB\)/home/Tests/MinApp\'
clang-9: error: no such file or directory: '\(riscv64\)/sdk-riscv64/lib'
clang-9: error: no input files
X512 ★★★★★
() автор топика
Ответ на: комментарий от Oleg_Iu
> export SYSLIBPATHS=" \
\"-L/Haiku 64 (USB)/home/Tests/MinApp (riscv64)/sdk-riscv64/lib\" \
\"-L/Haiku 64 (USB)/home/Tests/MinApp (riscv64)/sdk-riscv64/lib2\" \
"
> clang ${SYSLIBPATHS}
clang-9: error: no such file or directory: '"-L/Haiku'
clang-9: error: no such file or directory: '64'
clang-9: error: no such file or directory: '(USB)/home/Tests/MinApp'
clang-9: error: no such file or directory: '(riscv64)/sdk-riscv64/lib"'
clang-9: error: no such file or directory: '"-L/Haiku'
clang-9: error: no such file or directory: '64'
clang-9: error: no such file or directory: '(USB)/home/Tests/MinApp'
clang-9: error: no such file or directory: '(riscv64)/sdk-riscv64/lib2"'
clang-9: error: no input files
> clang "${SYSLIBPATHS}"
clang-9: error: no such file or directory: ' "-L/Haiku 64 (USB)/home/Tests/MinApp (riscv64)/sdk-riscv64/lib" "-L/Haiku 64 (USB)/home/Tests/MinApp (riscv64)/sdk-riscv64/lib2" '
clang-9: error: no input files
X512 ★★★★★
() автор топика
Ответ на: комментарий от X512

Корректный способ - изменить хранение на массив, чтобы сохранить число аргументов для clang. Например,

$ var=(-L"a b" -L"c d")
$ Args "${var[@]}"
2 args: <-La b> <-Lc d>

Используй функцию Args для отладки

Args() {
    printf "%d args:" $#
    printf " <%s>" "$@"
    echo
}
d_a ★★★★★
()
Ответ на: комментарий от d_a

Так вроде работает.

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

X512 ★★★★★
() автор топика
Ответ на: комментарий от X512

Нет здесь никакой магии. Замени clang на Args во всех своих примерах из шапки и посмотри какую ахинею сколько и каких аргументов ты отправляешь по факту в компилятор.

Ну и синтаксис для perfect forward массива ("${var[@]}") надо выучить, да.

d_a ★★★★★
()
Ответ на: комментарий от d_a

Попробовал вставить в объявление компилятора и опять не работает. Тоже надо массивы? В итоге надо чтобы это было с Makefile’ами совместимо.

> export CXX="clang++ ${SYSCFLAGS} ${SYSHEADERS[@]} ${SYSLIBPATHS[@]}"
> ${CXX} MinApp.cpp
clang-9: error: no such file or directory: '64'
clang-9: error: no such file or directory: '(USB)/home/Tests/MinApp'
clang-9: error: no such file or directory: '(riscv64)/sdk-riscv64/lib'
clang-9: error: no such file or directory: '64'
clang-9: error: no such file or directory: '(USB)/home/Tests/MinApp'
clang-9: error: no such file or directory: '(riscv64)/sdk-riscv64/lib2'
X512 ★★★★★
() автор топика
Ответ на: комментарий от X512

Это, как видишь, раскрывается в полную херню:

$ export CXX="clang++ ${SYSCFLAGS} ${SYSHEADERS[@]} ${SYSLIBPATHS[@]}"
$ Args ${CXX} MinApp.cpp
6 args: <clang++> <"-L/Haiku> <64> <(USB)/home/Tests/MinApp> <(riscv64)/sdk-riscv64/lib"> <MinApp.cpp>

Правильно было бы

"$CXX" $SYSCFLAGS "${SYSHEADERS[@]}" "${SYSLIBPATHS[@]}" MinApp.cpp

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

d_a ★★★★★
()
Ответ на: комментарий от d_a

«$CXX» $SYSCFLAGS «${SYSHEADERS[@]}» «${SYSLIBPATHS[@]}» MinApp.cpp

Завернуть внутрь ${CXX} это невозможно в принципе?

X512 ★★★★★
() автор топика
Ответ на: комментарий от X512

Если ты отрендеришь всё в одну строку, то естественно потеряешь всю разбивку на аргументы, которую мы заботливо готовили.

d_a ★★★★★
()
Ответ на: комментарий от d_a

Почему оно автоматически не работает как если бы не было вложенных переменных? Как это с Makefile совместить? Там делается такое:

C++		:= $(CXX)

$(OBJ_DIR)/%.o : %.cpp
	$(C++) -c $< $(INCLUDES) $(CFLAGS) -o "$@"
X512 ★★★★★
() автор топика

Наверное проще скрипт сделать, который будет выступать компилятором и содержать необходимые флаги.

X512 ★★★★★
() автор топика
Ответ на: комментарий от X512

Синтакисис make не знаю, но вижу что там свои совершенно отдельные переменные и вероятно свои отдельные правила подстановки. Впрочем, трюк с отладкой через printf " <%s>" $(C++) -c $< $(INCLUDES) $(CFLAGS) -o "$@" можно и в Makefile вставить, и узнать кто развалил путь с пробелами.

d_a ★★★★★
()
$ ls -l
итого 0
$ path1="path with spaces and 'quotes'"
$ path2="path with 'quotes' and spaces"
$ touch "$path1" "$path2"
$ ls -l
итого 0
-rw-r--r-- 1 user user 0 мая 17 17:51 "path with 'quotes' and spaces"
-rw-r--r-- 1 user user 0 мая 17 17:51 "path with spaces and 'quotes'"
$ combined=${path1@Q}
$ echo $combined
'path with spaces and '\''quotes'\'''
$ combined+=" "
$ combined+=${path2@Q}
$ eval ls -l ${combined}
-rw-r--r-- 1 user user 0 мая 17 17:51 "path with 'quotes' and spaces"
-rw-r--r-- 1 user user 0 мая 17 17:51 "path with spaces and 'quotes'"

${...@Q} это специфический для bash синтаксис.

i-rinat ★★★★★
()
Ответ на: комментарий от X512
$ SYSCFLAGS="-f1 -f2"
$ SYSHEADERS=(/212/33 /434/232)
$ CXX='clang++ ${SYSCFLAGS} "${SYSHEADERS[@]}"'
$ eval Args ${CXX} MinApp.cpp
6 args: <clang++> <-f1> <-f2> </212/33> </434/232> <MinApp.cpp>
anonymous
()
Ответ на: комментарий от X512

Завернуть внутрь ${CXX} это невозможно в принципе?

Ваши проблемы в том, что вы смешиваете сущности. CXX - это одна команда или команда с аргументами, а какой символ должен быть разделением аргументов, а почему тут - пробел в одном аргументе, а тут — это разделитель аргументов? То есть вы сейчас можете ответить так, а завтра захочется чуть по другому, а уже всё в кучу намешано.

Как это с Makefile совместить?

В Makefile $(VAR) - это таки массивы, если вы и на массивами воспользуетесь на bash, что вам уже предлагали, то всё и получится.

Наверное проще скрипт сделать, который будет выступать компилятором и содержать необходимые флаги.

Ну да, называется — врапперы, вполне юзабельно.

vodz ★★★★★
()
Ответ на: комментарий от anonymous

eval Args ${CXX} MinApp.cpp

Ну и нафига так небезопасно, если по аналогии

ARGS=(clang++ ${SYSCFLAGS} "${SYSHEADERS[@]}")

vodz ★★★★★
()
Ответ на: комментарий от vodz

Ну да, называется — врапперы, вполне юзабельно.

В итоге так и сделал. Работает.

X512 ★★★★★
() автор топика
Ответ на: комментарий от EXL

Господи, какой же Bash убогий

Убожество ещё то.

anonymous
()
3 июля 2021 г.
Ответ на: комментарий от EXL

Господи, какой же Bash убогий.

Нормальный. Более удобной командной оболочки человечество пока не изобрело.

Чтобы наступить на проблему как у ТС-а, нужно специально ставить цель отстрелить себе ногу.

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

В целом для сборки не следует использовать пути с пробелами, так как отвалиться может не только шелл-скрипт, но и много еще чего.

wandrien ★★
()
Ответ на: комментарий от EXL

Это не баш убогий. Это пользователи баша тупые и ленивые. Никаких существенных проблем с пробелами в баше нет.

anonymous
()
Ответ на: комментарий от wandrien

В целом для сборки не следует использовать пути с пробелами, так как отвалиться может не только шелл-скрипт, но и много еще чего.

Ещё одно доказательство что Bash defective by design. Я буду использовать и пробелы и юникодные символы в пути, а говнокод пусть отваливается.

Ещё убогие Autotools могут запросто отвалиться из-за пробелов в пути.

Более удобной командной оболочки человечество пока не изобрело.

Python, Lua.

Чтобы наступить на проблему как у ТС-а, нужно специально ставить цель отстрелить себе ногу.

Даже в Си не так просто отстрелить себе ногу как в Bash.

X512 ★★★★★
() автор топика
Последнее исправление: X512 (всего исправлений: 3)
Ответ на: комментарий от anonymous

Ты поставил себе питон как дефолт шелл?

Одно время на тестовой сборке Haiku ставил Lua как default shell потому что Bash не был собран под RISC-V (в Bash используются Craptools).

X512 ★★★★★
() автор топика
Последнее исправление: X512 (всего исправлений: 1)
Ответ на: комментарий от X512

странный ты, говоришь:

bash убогий

python, lua лучшие шеллы

но в качестве шелла продолжаешь использовать bash

любишь страдать?

anonymous
()
Ответ на: комментарий от X512

Даже в Си не так просто отстрелить себе ногу как в Bash.

С кривыми руками легко и в Си, и в bash, и на ровном месте.

Python, Lua.

Э-ге-гей, братья по разуму! Как там у вам на Марсе?

wandrien ★★
()
Ответ на: комментарий от X512

как же так, почему не швятой powershell от гениев архитектуры?

anonymous
()
Ответ на: комментарий от wandrien

Нормальный. Более удобной командной оболочки человечество пока не изобрело.

Речь не идёт про командную оболочку, речь про переусложнённый синтаксис скриптов, наводнённый сабжевыми проблемами, десятью видами кавычек и другими mindfuck’ами вроде Простая конструкция на баше выдает ошибку command not found.

А оболочки удобнее Bash существуют давно: Fish, zsh, интересен даже PowerShell, где делается ставка на объекты, а не парсинг текстового выхлопа, что позволяет справляться с задачами вроде Адский разбор вывода ps aux регулярками гораздо менее малой кровью.

EXL ★★★★★
()
Ответ на: комментарий от anonymous

Это не баш убогий. Это пользователи баша тупые и ленивые. Никаких существенных проблем с пробелами в баше нет.

Повторяю, никаких проблем, нет. Вы всё придумываете.
Повторяю, никаких проблем, нет. Вы всё придумываете.
Повторяю, никаких проблем, нет. Вы всё придумываете.

https://github.com/MrMEEE/bumblebee-Old-and-abbandoned/issues/123

Упс.

EXL ★★★★★
()
Ответ на: комментарий от EXL

Простая конструкция на баше выдает ошибку command not found.

Мне даже по ссылке лень переходить. Зайди в раздел Development и почитай, что там пишут новички относительного любого ЯП.

А оболочки удобнее Bash существуют давно: Fish, zsh

zsh, bash — это всё из одной области. Убогий fish не считаем, он бесполезен.

интересен даже PowerShell

А вот и «швятой powershell от гениев архитектуры» специально для анонима выше. Только чо-т не взлетает.

где делается ставка на объекты, а не парсинг текстового выхлопа, что позволяет справляться с задачами вроде Адский разбор вывода ps aux регулярками гораздо менее малой кровью.

И даешь ссылку на топик, в котором от баша присутствует только символ ‘|’. Хотел написать много яда на этот счёт, но пока завтракал, подобрел, и стало лень.

То есть, с одной стороны, zsh ­— удобная оболочка, а с другой, она же и виновата в том, что вызываемые команды не используют машиночитаемый формат, а пользователи пытаются пристроить sed в каждой дырке. Как по мне, логика утеряна.

wandrien ★★
()
Ответ на: комментарий от wandrien

разумеется, императивная лапша же

anonymous
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.