Преобразовать массив в аргументы команды?

Из сценария оболочки Вы будете ограничены для завершения строк. Необходимо будет использовать C/Perl/Python/whatever для более прекрасного гранулярного чтения.

while read line; do
  # do something based on content of $line; remember to quote it
done </dev/input/event0
40
21.01.2012, 01:08
3 ответа

Я предпочел бы плоскость bash путь:

command "${my_array[@]/#/-}" "$1"

Одной причиной этого являются пробелы. Например, если Вы имеете:

my_array=(option1 'option2 with space' option3)

sed основанные решения преобразуют его в -option1 -option2 -with -space -option3 (длина 5), но вышеупомянутое bash расширение преобразует его в -option1 -option2 with space -option3 (длина все еще 3). Редко, но иногда это важно, например:

bash-4.2$ my_array=('Ffoo bar' 'vOFS=fiz baz')
bash-4.2$ echo 'one foo bar two foo bar three foo bar four' | awk "${my_array[@]/#/-}" '{print$2,$3}'
 two fiz baz three
43
27.01.2020, 19:35

Я не обработал это, это было в массиве и думало разделенное от пробела в строке. Это решение будет работать с этим, но, учитывая, что это - массив, пойдите с решением manatwork (@{my_array[@]/#/-}).


Это не слишком плохо с sed и подоболочка. То, насколько легкий regex, зависит от того, что можно гарантировать об опциях. Если опции являются всем одним "словом" (a-zA-Z0-9 только), затем простая граница слова начала (\<) будет достаточен:

command $(echo $my_array | sed 's/\</-/g') "$1"

Если Ваши опции имеют другие символы (скорее всего, -), Вам будет нужно что-то немного более сложное:

command $(echo $my_array | sed 's/\(^\|[ \t]\)\</\1-/g') "$1"

^ соответствует началу строки, [ \t] соответствует пространству или вкладке, \| соответствия любая сторона (^ или [ \t]), \( \) группы (для \|) и хранит результат, \< соответствует запуску слова. \1 начинает замену путем хранения первого соответствия от parens (\(\)), и - конечно, добавляет тире, в котором мы нуждаемся.

Они работают с гну sed, если они не работают с Вашим, сообщить мне.

И если Вы будете использовать то же самое многократно, можно хотеть просто вычислить его однажды и сохранить его:

opts="$(echo $my_array | sed 's/\(^\|[ \t]\)\</\1-/g')"
...
command $opts "$1"
command $opts "$2"
2
27.01.2020, 19:35
  • 1
    Это не работало с Mac OS X sed, таким образом, я должен был использовать gsed (Я установил использование homebrew). Другая вещь: вместо echo $my_array, Я должен был сделать echo ${my_array[@]} получить все объекты от my_array: echo $my_array давал мне только первый элемент. Но спасибо за ответ и объяснение regex, особенно о "границе слова", это чрезвычайно полезно. :) –  Somebody still uses you MS-DOS 20.01.2012, 06:50
  • 2
    я хотел бы выйти из сценария, если sed системы не совместим с этой граничной функцией слова. Как я сделал бы это? Печать sed версия и сравнение его? От которой версии sed была добавлена эта опция? –  Somebody still uses you MS-DOS 20.01.2012, 07:00
  • 3
    @SomebodystillusesyouMS-DOS Моя первая мысль состоит в том, чтобы проверить непосредственно, работает ли это - [ $(echo x | sed 's/\</y/') == "yx" ] || exit. –  Kevin 20.01.2012, 07:09
  • 4
    Это повредится, если какой-либо из элементов массива будет содержать специальные символы, наиболее очевидно, и непреклонно пробел. –  Gilles 'SO- stop being evil' 21.01.2012, 01:09
  • 5
    @SomebodystillusesyouMS-DOS, Gilles прав, необходимо изменить Ваш принимать к manatwork. –  Kevin 21.01.2012, 18:44
[srikanth@myhost ~]$ sh sample.sh 

-option1 -option2 -option3

[srikanth@myhost ~]$ cat sample.sh

#!/bin/bash

my_array=(option1 option2 option3)

echo ${my_array[@]} | sed 's/\</-/g'
0
27.01.2020, 19:35

Теги

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