Это работает & mdash; это не то, что я бы использовал, но это «работает». Давайте создадим скрипт teredo
для установки переменной среды TEREDO_WORMS
:
#!/bin/ksh
export TEREDO_WORMS=ukelele
exec $SHELL -i
Он будет интерпретироваться оболочкой Korn, экспортирует переменную среды, а затем заменит себя новой интерактивной оболочкой.
Перед запуском этого скрипта мы установили SHELL
в среде для оболочки C, а переменная среды TEREDO_WORMS
не установлена:
% env | grep SHELL
SHELL=/bin/csh
% env | grep TEREDO
%
Когда скрипт запущен, вы в новой оболочке - другая интерактивная оболочка C, но установлена переменная окружения:
% teredo
% env | grep TEREDO
TEREDO_WORMS=ukelele
%
При выходе из этой оболочки исходная оболочка вступает во владение:
% exit
% env | grep TEREDO
%
Среда переменная не установлена в среде исходной оболочки. Если вы используете exec teredo
для запуска команды, то исходная интерактивная оболочка заменяется оболочкой Korn, которая задает среду, а затем, в свою очередь, заменяется новой интерактивной оболочкой C:
% exec teredo
% env | grep TEREDO
TEREDO_WORMS=ukelele
%
Если вы наберете exit
(или Control-D kbd>), то ваша оболочка закроется, возможно, выйдет из этого окна или вернет вас на предыдущий уровень оболочки, с которого начались эксперименты.
Тот же механизм работает для оболочки Bash или Korn. Вы можете обнаружить, что подсказка после команд выхода появляется в забавных местах.
Обратите внимание на обсуждение в комментариях. Это не решение, которое я бы рекомендовал, но оно достигает заявленной цели единого сценария, чтобы установить среду, которая работает со всеми оболочками (которые принимают опцию -i
для создания интерактивной оболочки). Вы также можете добавить "$@"
после опции для передачи любых других аргументов, что может сделать оболочку пригодной для использования в качестве общего инструмента 'set environment and execute command'. Возможно, вы захотите опустить -i
, если есть другие аргументы, приводящие к:
#!/bin/ksh
export TEREDO_WORMS=ukelele
exec $SHELL "${@-'-i'}"
Бит "${@-'-i'}"
означает «если список аргументов содержит хотя бы один аргумент, используйте исходный список аргументов; в противном случае замените -i
несуществующими аргументами ».
Вам нужно будет создать IComparer, который будет сравнивать элементы на основе состояния вашего другого списка. Преимущество использования IComparer заключается в том, что вы сможете встроить логику кэширования в свой класс, чтобы избежать повторных поисков IndexOf (), если вам нужна такая оптимизация. Кроме того, вы сможете поддерживать несколько «других» списков, которые можно использовать при необходимости.
class ItemTpComparer : IComparer<itemTp>
{
private IList<codeTp> otherList;
public ItemTpComparer(IList<codeTp> otherList)
{
this.otherList = otherList;
}
public int Compare(itemTp a, itemTp b)
{
return otherList.IndexOf(a.Code) - otherList.IndexOf(b.Code);
}
}
И для выполнения сортировки:
myList.Sort(new ItemTpComparer(otherList));
Извините, если что-то не так, у меня здесь не установлен редактор C #, но он примерно такой:
Array.Sort(
itemTps,
delegate(ItemTp a, ItemTp b)
{
return secondList.IndexOf(a.Code) - secondList.IndexOf(b.Code);
});
Примечание: это может быть не самый эффективный способ, а также отсутствует проверка, содержит ли второй список Код вообще.
[Edit] Как сказал Мердад, Array.Sort
не работает для общего IList
. Чтобы отсортировать массив на месте, вам нужно будет использовать метод ArrayList.Adapter
, чтобы создать оболочку, а затем отсортировать ее. Поскольку ArrayList.Sort
не поддерживает сравнение делегатов, вам необходимо поместить анонимный делегат в реализацию IComparer
,.
Если вам нужно его отсортировать в отдельном списке, тогда имеет смысл использовать описанную выше логику, сначала создав массив.
Используя C # 3 и LINQ to Objects, я бы просто создал новый список вместо того, чтобы пытаться отсортировать существующий:
void Example()
{
IList<string> codes;
IList<ItemTp> itemTps;
itemTps = codes.Select(code => itemTps.Single(itp => itp.Code == code)).ToList();
}