Подтвердить что ты не робот

Лямбда-функции в bash

Есть ли способ реализовать/использовать лямбда-функции в bash? Я думаю о чем-то вроде:

$ someCommand | xargs -L1 (lambda function)
4b9b3361

Ответ 1

Я не знаю, как это сделать, но вы можете выполнить то, что вы пытаетесь сделать, используя:

somecommand | while read -r; do echo "Something with $REPLY"; done

Это также будет быстрее, так как вы не будете создавать новый процесс для каждой строки текста.

[EDIT 2009-07-09] Я сделал два изменения:

  • Включено литровое предложение использовать -r для отключения обработки обратной косой черты - это означает, что обратные косые черты на входе будут переданы без изменений.
  • Вместо того, чтобы указывать имя переменной (например, X) в качестве параметра read, мы позволяем read присваивать его переменной по умолчанию REPLY. Это имеет приятный побочный эффект для сохранения ведущих и конечных пространств, которые в противном случае удаляются (хотя внутренние пространства сохранены).

Из моих наблюдений вместе эти изменения сохраняют все, кроме буквальных символов NUL (ASCII 0) на каждой строке ввода.

[EDIT 26/7/2016]

Согласно комментарию Evi1M4chine, установка $IFS в пустую строку перед запуском read X (например, с помощью команды IFS='' read X) также должна сохранять пробелы в начале и конце при сохранении результата в $X, что означает вы не должны использовать $REPLY.

Ответ 2

если вам нужны истинные функции, а не только каналы или циклы while (например, если вы хотите передать их, как если бы они были данными) Id просто не делал лямбда и определял фиктивные функции с повторяющимся фиктивным именем, чтобы использовать сразу же, и выбросить потом. Например:

# An example map function, to use in the example below.
map() { local f="$1"; shift; for i in "[email protected]"; do "$f" "$i"; done; }

# Lambda function [λ], passed to the map function.
λ(){ echo "Lambda sees $1"; }; map λ *

Как и в правильных функциональных языках, нет необходимости передавать параметры, так как вы можете обернуть их в закрытие:

# Let’s say you have a function with three parameters
# that you want to use as a lambda:
# (As in: Partial function application.)
trio(){ echo "$1 Lambda sees $3 $2"; }

# And there are two values that you want to use to parametrize a
# function that shall be your lambda.
pre="<<<"
post=">>>"

# Then you’d just wrap them in a closure, and be done with it:
λ(){ trio "$pre" "$post" "[email protected]"; }; map λ *

Id утверждает, что его еще меньше, чем все другие решения, представленные здесь.

Ответ 3

Как насчет этого?

somecommand | xargs -d"\n" -I{} echo "the argument is: {}"

(предполагается, что каждый аргумент является строкой, в противном случае - разделителем)

Ответ 4

если вы хотите использовать только xargs (например, параллельную опцию -P N) и только bash в качестве функционального кода, тогда bash -c может использоваться как параметр для xargs.

seq 1 10 | tr '\n' '\0' | xargs -0 -n 1 bash -c 'echo any bash code $0'

tr и -0 используются здесь, чтобы отключить любые замены параметров xargs.

Ответ 5

Да. Можно передать строковую переменную, представляющую вызов команды, а затем выполнить команду с помощью eval.

Пример:

command='echo howdy'
eval "$command"

Ответ 6

Уловка eval уже упоминалась, но вот мой расширенный пример закрытия bash:

#!/usr/bin/env bash

set -e

function multiplyBy() {
    X="$1"

    cat <<-EOF
        Y="\$1"
        echo "$X * \$Y = \$(( $X * \$Y ))"
    EOF
}

function callFunc() {
    CODE="$1"
    shift

    eval "$CODE"
}

MULT_BY_2='multiplyBy 2'
MULT_BY_4='multiplyBy 4'

callFunc "$MULT_BY_2" 10
callFunc "$MULT_BY_4" 10

PS Я только что придумал это для совершенно другой цели и просто искал в Google, чтобы узнать, использует ли это sb. Мне действительно нужно было оценить функцию многократного использования в контексте (оболочке) основного скрипта.