Передача команды с аргументами и перенаправление на функцию

На основе Вычислить средние значения строки для подмножества столбцов

> df = read.table('file')
> 
> data.frame(ID=df[,0], DwoC_2318_mean=rowMeans(df[1:3]), DwoC_3395_mean=rowMeans(df[4:6]))
                   DwoC_2318_mean DwoC_3395_mean
Ku8QhfS0n_hIOABXuE       4.716736       4.343313
Bx496XsFXiAlj.Eaeo       6.369502       5.881424
W38p0ogk.wIBVRXllY       7.715556       7.645857
QIBkqIS9LR5DfTlTS8       5.696061       5.177421
BZKiEvS0eQ305U0v34       6.176525       5.667866
6TheVd.HiE1UF3lX6g       5.342324       5.237884
> 

1
13.04.2021, 19:28
2 ответа

eval "$@"сделал бы это:

#!/bin/bash

f() {
  echo "command: $@"
  eval "$@"
}

но в целом очень небезопасно его использовать, хоть ты и увидишь здесь и там .

0
28.04.2021, 22:52
f() {
  echo "command: $@"
  $@
}

В общем, вам следует использовать "$@", и здесь тоже по обычнымпричинам .

Но вы правы, выполнение такой команды не обрабатывает операторы оболочки, будь то перенаправления или что-то вроде &&. Вы можете изменить функцию на evalкоманду, которую она получает, которая будет обрабатывать перенаправления, а также все остальное.

В частности, передача произвольных имен файлов снова станет сложной. Например. это приведет к запуску lsв двух файлах fooи bar:

.
run_with_eval() {
    eval "$@"
}
file='foo bar'
run_with_eval ls -l "$file" 

Вам придется организовать передачу имени файла в кавычках для оболочки, что несколько неудобно и чревато ошибками -.

Но если вам нужно только перенаправление, а еще лучше, только выходное перенаправление с >,вы можете заставить функцию обрабатывать это вручную:

#!/bin/bash
run_with_redir() {
    local redir=
    if [[ $1 = '>' ]]; then
        redir=$2
        shift 2
    fi
    ## whatever else you do
    if [[ $redir ]]; then
        "$@" > "$redir"
    else
        "$@"
    fi
}

run_with_redir echo "normal command, no redirection"
run_with_redir ">" output.txt echo "this gets redirected to output.txt"

То есть вызов функции с >и именем файла в качестве первых двух аргументов запускает остальные как команду с перенаправлением вывода. Без >команда выполняется нормально. Обратите внимание, что ">"должен быть заключен в кавычки при вызове функции, иначе мы снова получим перенаправление вывода всей функции. Расширение этого для поддержки, например. >>должно быть простым, даже если оно повторяется.

Это также должно работать в более сложных случаях:

run_with_redir ">" "output file with space.txt" ls -l "other file with space"
1
28.04.2021, 22:52

Теги

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