Как использовать xargs с функцией в рыбной оболочке?

Мне нужно использовать xargs для параллельного вызова функции в рыбной оболочке. Я пробовал это:

#!/bin/fish

function func
    echo $argv
end

echo 'example1' 'example2' | xargs -n1 func

Но я получил это:

xargs: func: No such file or directory

Итак, как я могу заставить его работать?

Используя bash, это сработало:

#!/bin/bash

function func {
    echo $1
}
export -f func

echo 'example1' 'example2' | xargs -n1  bash -c 'func $@' _

person Sérgio Mucciaccia    schedule 11.06.2018    source источник


Ответы (2)


Как сказал Куртис, xargs не будет работать с функциями. Его можно заставить работать, запустив другую оболочку, но это хак.

Что, вероятно, будет работать лучше для вас, так это вообще не использовать xargs.

Вместо

echo 'example' | xargs func

просто запустите func example.

Как правило, для этого следует использовать подстановки команд fish.

Итак, вместо

somecommand | xargs func

использовать

func (somecommand)

это разделит вывод somecommands на символы новой строки, что, строго говоря, более строго, чем xargs (который по умолчанию будет разделяться на «пробелы» и новую строку, но позволит использовать кавычки и экранирование в стиле оболочки), что обычно то, что вы хотите.

person faho    schedule 11.06.2018
comment
Я хочу использовать xargs из-за опции -n1, чтобы я мог вызывать функцию много раз параллельно. В xargs есть и другие полезные опции. Нет ли способа вызвать функцию как команду, создав новый процесс? - person Sérgio Mucciaccia; 12.06.2018
comment
Нет. Вам придется вызывать fish -c вместо функции напрямую. То же самое вы делаете с bash, за исключением того, что у рыбы нет возможности экспортировать функцию, поэтому она должна быть доступна глобально (например, через автозагрузку) или явно sourced. - person faho; 13.06.2018
comment
Кажется, я не могу передать параметры через fish -c. Например sh -c 'cat $0' 'a.txt' работает и аргумент a.txt передается в cat, а fish -c 'cat $argv' 'a.txt' не работает. Как я могу передать динамический аргумент команде fish -c? - person Sérgio Mucciaccia; 13.06.2018

Для команды xargs требуется и внешняя команда. Вы не можете дать ему функцию. То, что вы пытаетесь сделать, не будет работать с bash, zsh, ksh или любой подобной оболочкой. Это можно сделать, поместив функцию в файл с именем func, который находится в вашем PATH:

#!/bin/fish

function func
    echo $argv
end

func $argv

Теперь, когда он реализован как внешняя команда (скрипт оболочки), вы можете использовать его с xargs: echo 'example' | xargs func.

person Kurtis Rader    schedule 11.06.2018
comment
Он работал на bash, внося некоторые изменения. Как в этом ответе: stackoverflow.com/questions/11003418/ Нельзя ли сделать что-то подобное в рыбе? - person Sérgio Mucciaccia; 12.06.2018
comment
На мой взгляд, функция bash export -f some_func — это чушь. Причина использования функции оболочки в том, что она может изменить состояние текущей оболочки. Такой экспорт функции делает это невозможным. И, таким образом, вводит в заблуждение и глупо, поскольку вы можете добиться того же эффекта, используя мое решение. - person Kurtis Rader; 12.06.2018
comment
Я знаю, что могу поместить их в отдельные сценарии, но у меня здесь много функций, и я не хочу помещать каждую из них в отдельный сценарий для организации. - person Sérgio Mucciaccia; 12.06.2018
comment
Прочитайте мой ответ еще раз, @SérgioMucciaccia. В bash это работает только потому, что в bash есть анти-фича (то есть то, что никогда не должно было быть реализовано). Основная особенность функций оболочки заключается в том, что они могут изменять состояние оболочки. Функция export -f some_func по определению означает, что some_func не может изменять состояние текущей оболочки. В этом случае вы должны просто реализовать его как скрипт. Потому что это то, что происходит на заднем плане. - person Kurtis Rader; 13.06.2018