Обычно используется xargs , чтобы сделать вывод одной команды опцией другой команды. Например:
$ cat command1
#!/bin/sh
echo "one"
echo "two"
echo "three"
$ cat command2
#!/bin/sh
printf '1 = %s\n' "$1"
$ ./command1 | xargs -n 1 ./command2
1 = one
1 = two
1 = three
$
Но ... пока это был ваш вопрос, это не то, что вы действительно хотите знать.
Если вы не возражаете хранить свой tty в переменную, вы можете использовать переменную bash для замены:
$ tty=`tty`; who | grep -w "${tty#/dev/}"
ghoti pts/198 Mar 8 17:01 (:0.0)
(вы хотите использовать -w, потому что если вы находитесь на pts / 6, вы не должны видеть лоты pts / 60.)
Вы ограничены этим в переменной, потому что если вы попытаетесь поместить команду tty
в канал, она думает, что она больше не работает с терминалом.
$ true | echo `tty | sed 's:/dev/::'`
not a tty
$
Обратите внимание, что ничто в этом ответе пока не относится к bash. Поскольку вы используете bash, другим способом решения этой проблемы является замена процесса. Например, пока это не работает:
$ who | grep "$(tty | sed 's:/dev/::')"
Это делает:
$ grep $(tty | sed 's:/dev/::') < <(who)
Это довольно известное различие между Windows и Unix-подобными системами.
Независимо от того, что:
Итак, ключевая проблема здесь - действительно видимость .
Во всех случаях глобальные переменные (или функции) static
никогда не видны извне модуля (dll / so или executable). Стандарт C ++ требует, чтобы у них была внутренняя связь, что означает, что они не видны за пределами единицы перевода (которая становится объектным файлом), в которой они определены. Итак, это решает эту проблему.
Там, где это усложняется, вы имеете extern
глобальные переменные. Здесь ОС и Unix-подобные системы совершенно разные.
В случае Windows (.exe и .dll) глобальные переменные extern
не являются частью экспортированных символов. Другими словами, разные модули никоим образом не знают глобальных переменных, определенных в других модулях. Это означает, что вы получите ошибки компоновщика, если попытаетесь, например, создать исполняемый файл, который должен использовать переменную extern
, определенную в DLL, потому что это недопустимо. Вам нужно будет предоставить объектный файл (или статическую библиотеку) с определением этой внешней переменной и связать его статически с как с исполняемым файлом, так и с DLL, в результате получится две различные глобальные переменные (одна из которых принадлежит исполняемый и один, принадлежащий к DLL).
Чтобы фактически экспортировать глобальную переменную в Windows, вы должны использовать синтаксис, аналогичный синтаксису экспорта / импорта функции, то есть:
#ifdef COMPILING_THE_DLL
#define MY_DLL_EXPORT extern "C" __declspec(dllexport)
#else
#define MY_DLL_EXPORT extern "C" __declspec(dllimport)
#endif
MY_DLL_EXPORT int my_global;
Когда вы это делаете, глобальная переменная добавляется в список экспортированных символов и может быть связана как и все другие функции.
В случае Unix-подобных сред (например, Linux) динамическая библиотеки, называемые «общие объекты» с расширением .so
экспортируют все extern
глобальные переменные (или функции). В этом случае, если вы выполняете время загрузки , связанное из любого места в общий файл объекта, тогда глобальные переменные являются совместно используемыми, т. Е. Связаны друг с другом как единое целое. В принципе, Unix-подобные системы разработаны таким образом, что практически нет никакой разницы между связыванием со статической или динамической библиотекой. Опять же, ODR применяется по всем направлениям: глобальная переменная extern
будет разделяться между модулями, а это означает, что у нее должно быть только одно определение для всех загруженных модулей.
Наконец, в обоих случаях для Windows или Unix-подобных системах вы можете выполнить время выполнения динамической библиотеки, то есть используя либо LoadLibrary()
/ GetProcAddress()
/ FreeLibrary()
, либо dlopen()
/ dlsym()
/ dlclose()
. В этом случае вам нужно вручную получить указатель на каждый из символов, которые вы хотите использовать, и который включает в себя глобальные переменные, которые вы хотите использовать. Для глобальных переменных вы можете использовать GetProcAddress()
или dlsym()
так же, как и для функций, при условии, что глобальные переменные являются частью списка экспортированных символов (по правилам предыдущих абзацев).
И, конечно же, в качестве необходимой окончательной заметки: следует избегать глобальных переменных. И я считаю, что текст, который вы цитировали (о том, что «неясно»), относится точно к различиям, специфичным для платформы, которые я только что объяснил (динамические библиотеки на самом деле не определены стандартом C ++, это платформа, гораздо менее надежна / переносима).
MY_DLL_EXPORT ResourceObject my_global;
, гдеResourceObject
имеет нетривиальный dtor. Будет ли dtor вызываться, когда программа, связывающая DLL, завершается? – AntiMoron 15 October 2015 в 08:12