Переменные среды не установлены, когда моя функция вызвана в конвейере

(отредактированный, поскольку я неправильно понял вопрос, который был с тех пор отредактирован также),

Лучшее, которое можно сделать, должно извлечь, удалить и повторно сжать весь файл.

unxz < foobar-old.tar.xz | tar --delete foo/bar | xz > foobar-new.tar.xz

Не возможно удалить файлы из tar непосредственно.

tar является потоком, первоначально предназначенным для ленточных накопителей, которые не делают случайный, ищет хорошо - в то время как в теории могло быть возможно в дисковой файловой системе перфорировать дыру / переписывают остающийся файл, со сжатием, вопрос спорен как большинство, если не все методы сжатия в большой степени зависят от содержания, которое произошло ранее в файле. Чтобы сделать это на месте, Вам было бы нужно очень детальное знание об обоих метод сжатия, а также формат файла tar. Это - сложность к точке, которую никто даже не побеспокоил бы ею. Более дешево просто иметь в наличии файлы и проигнорировать их.

При необходимости в этой функциональности tar, вероятно, не, что Вы хотите.

10
06.06.2014, 20:13
3 ответа

Каждая часть конвейера (т.е. каждая сторона конвейера) выполняется в отдельном процессе (называемом подоболочкой, когда оболочка разветвляет подпроцесс для запуска часть сценария). В par_set PIPE FAILS | sed -e's / FAILS / BARFS / ' переменная PIPE устанавливается в подпроцессе, который выполняет левую часть конвейера. Это изменение не отражается в родительском процессе (переменные среды не передаются между процессами, они наследуются только подпроцессами.

Левая часть конвейера всегда выполняется в подоболочке. Некоторые оболочки (ATT ksh, zsh) запускать правую часть в родительских оболочках; большинство также запускают правую часть в подоболочке.

Если вы хотите как перенаправить вывод части сценария, так и запустить эту часть в родительской оболочке, в ksh / bash / zsh, вы можете использовать замену процесса .

par_set PROCESS SUBSTITUTION > >(sed s/ION/ED/)

С любой оболочкой POSIX вы можете перенаправить вывод в именованный канал.

mkfifo f
<f grep NAMED= &
par_set NAMED PIPE >f

О, и вам не хватает кавычек вокруг подстановок переменных , ваш код разбивается на такие вещи, как par_set name 'значение' с пробелами 'звездочка' * '.

export "${PAR}=${VAL}"
…
par_set "$@"
8
27.01.2020, 20:02

Вы указываете на подоболочки - их можно обойти с помощью некоторых изысков в оболочке вне конвейера - но более сложная часть проблемы связана с параллелизм конвейера .

Все элементы процесса конвейера начинаются с один раз , поэтому проблему будет легче понять, если вы посмотрите на нее так:

{ sleep 1 ; echo $((f=1+2)) >&2 ; } | echo $((f))
###OUTPUT
0
...
3

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

Я не могу понять, в чем суть вашей функции - для какой цели она служит тому, что export еще не выполняет? Или даже просто var = val ? Например, вот почти тот же конвейер снова:

pipeline() { 
    { sleep 1
      echo "f=$((f=f+1+2))" >&3
    } | echo $((f)) >&2
} 3>&1

f=4 pipeline

###OUTPUT

4
...
f=7

И с экспортом :

export $(f=4 pipeline) ; pipeline

###OUTPUT:

4
7
...
f=10

Итак, ваша вещь может работать так:

par_set $(echo PIPE FAILS | 
    sed 's/FAIL/WORK/;/./w /path/to/log')

Которая будет записывать в файл sed и передайте его вашей функции как разделение оболочки «$ @» .

Или, как вариант:

$ export $(echo PIPE FAILS | sed 's/ FAIL/=WORK/')
$ par_set $PIPE TWICE_REMOVED
$ echo "WORKS = "$WORKS
WORKS = TWICE_REMOVED

Однако, если бы я собирался написать вашу функцию, она, вероятно, выглядела бы так:

_env_eval() { 
    while ${2+:} false ; do
       ${1:+export} ${1%%["${IFS}"]*}="${2}" || :
       shift 2
    done
}
0
27.01.2020, 20:02

Это не работает, потому что каждая сторона канала работает в подоболочке в bash , а переменные, установленные в подоболочке, являются локальными для этой подоболочки.

Обновление:

Похоже, что легко передать переменные из родительской в ​​дочернюю оболочку, но действительно трудно сделать это по-другому. Некоторыми обходными путями являются именованные каналы, временные файлы, запись в стандартный вывод и чтение в родительском элементе и т. Д.

Некоторые ссылки:

http://mywiki.wooledge.org/BashFAQ/024
https: // stackoverflow .com / q / 15541321/3565972
https://stackoverflow.com/a/15383353/3565972
http://forums.opensuse.org/showthread.php/458979-How-export-variable-in -subshell-back-out-to-parent

3
27.01.2020, 20:02

Теги

Похожие вопросы