2009-06-08 2 views
4

я работаю с утилитой (unison, но это не точка), который принимает параметры, как:манипулировать параметрами в ш

$ unison -path path1 -path path2 -path path3 

Я хотел бы написать ш сценарий, который я мог бы работать так:

$ myscript path1 path2 path3 

Я надеюсь на решение, совместимое с Posix, но также будет полезно использовать bash.

Я предполагаю, что это должно быть что-то вроде:

#!/bin/sh 
unison ${*//-path } 

Но это не работает.

EDIT: Хорошо, я думаю, что есть кое-что:

#!/bin/bash 
PARAMS= 
for arg in "[email protected]" 
do 
    PARAMS+=" -path '$arg'" 
done 
unison $PARAMS 

Проблемы это работает только в Баш, и я уверен, что есть лучший способ привести параметры.

+0

Are вы надеетесь на однострочное решение, которое не включает цикл 'for'? – eduffy

+0

Любое решение действительно – itsadok

+0

Введение одиночных кавычек, вероятно, плохая идея. Как написано, цитаты видны командой unison, которая не является тем, что вы хотите. Защита внешних аргументов одинарными кавычками в порядке, если у вас нет ни одной кавычки в аргументах, - но вам, вероятно, понадобится eval, чтобы заставить ее работать правильно. –

ответ

5

Неконтролируемый, это может быть столь же просто, как:

exec unison -path $1 -path $2 -path $3 

Если вы не вставлять пробелы в именах путей, то вы можете иметь дело с переменным числом аргументов с:

arglist="" 
for path in "[email protected]" 
do 
    arglist="$arglist -path $path" 
done 
exec unison $arglist 

Если у вас есть пробелы в именах путей, вам придется работать намного сложнее; Я обычно использую пользовательскую программу под названием escape, который цитирует аргументы, которые нуждаются в цитировании и eval:

arglist="" 
for path in "[email protected]" 
do 
    path=$(escape "$path") 
    arglist="$arglist -path $path" 
done 
eval exec unison "$arglist" 

Хочу отметить, что с помощью Perl или Python бы аргументы обработки с пробелами в них проще - но вопрос касается оболочки.

Возможно, в Bash также возможно использовать переменную массива оболочки - собрать аргументы в массив и передать массив в качестве аргументов в команду unison.

1

Если вы хотите сильно Баш конкретной версии, вы можете попробовать

 
#! /bin/sh 

eval eval exec \ 
    unison -path\\ \\\"{$(eval echo \\\"\\\${1..$#}\\\" | sed 's/ /,/g')}\\\" 

Если удалить все тройные обратные косые черты кавычек символов, это становится легче понять, но я не буду портить удовольствие объяснив это :-)

Главным осложнением является обработка имен файлов с пробелами. Это объясняет котировку с тройным обратным люком и двойную оценку.

+0

Поддерживается для сумасшедшего однострочного – itsadok

+0

WTF? Если вы собираетесь использовать определенный уровень, то Right Thing - использовать массивы - таким образом вы получите преимущество простого, легко читаемого кода, который может быть написан четко, чтобы, очевидно, не иметь ошибок, а не требовать полагаться на отсутствие явных ошибок. –

+0

Этот ответ должен был быть странным, загадочным и юмористическим, а не примером «Правой вещи». – Idelic

4

Если вы используете массивы Bash, все ваши проблемы с цитированием уходят.

#!/bin/bash 
args=() 
for i in "[email protected]"; do 
    # With Bash >= 3: 
    args+=(-path "$i") 
    # +=() doesn't work in Bash 2 
    # args=("${args[@]}" -path "$i") 
done 
exec unison "${args[@]}" 
+0

+1 для массивов вместо беспорядочных и хрупких цитат/экранов –

+0

Ditto @Gordon, плюс спасибо за включение бит о совместимости Bash 2! –

3

В Bash, вы можете использовать "${@/#/-path }", который заменит начало каждого позиционного параметра с «-path». Для представления конца строки используйте % вместо #.

Простой демонстрационный пример с использованием sed и повторных -e вариантов.(. Конечно, есть более эффективные способы использования sed)

#!/bin/bash 
echo "Resulting arguments: ${@/#/-e }" 
sed "${@/#/-e }" 

И работает это так:

$ echo abc | demo s/a/A/ s/b/B/ 

Получают:

Resulting arguments: -e s/a/A/ -e s/b/B/ 
ABc 
1

Вот как вы можете удовольствие цитаты ваши персонажи:

job_strategy() 
{ 
    local p 
    for p in "[email protected]"; do 
    printf '-path\000%s\000' "$p" 
    done 
} 

job_process() 
{ 
    xargs -0 unison 
} 

job_strategy "path1" "path2" "path3" | job_process 
+1

+1. Тем не менее, это 'xargs -0' POSIX? Мое впечатление, что это расширение GNU. –

+0

Согласно man-странице FreeBSD 'xargs -0' является POSIX. –

+0

Это не указано в http://pubs.opengroup.org/onlinepubs/009696699/utilities/xargs.html –