Скрипт Bash, который вызывает программу с некоторыми звёздочками в аргументах
1103
kirelagin
Я провел последний час или около того, пытаясь написать довольно простой сценарий bash, и я никогда не чувствовал себя настолько глупым.
Итак, у меня есть список строк (которые являются спецификациями селектора пакетов для менеджера пакетов, если это имеет значение), которые могут содержать звездочки. Мне нужно создать командную строку, сохраняя эти звездочки, а затем вызвать программу. Вот моя наивная попытка:
xs="foo/bar */*" xs_cmd="" for x in $xs; do xs_cmd="$xs_cmd -0 $x " done echo $xs_cmd
Мне нужно, чтобы echoзвонок был эквивалентен
echo -0 foo/bar -0 '*/*'
какие выводы -0 foo/bar -0 */*.
PS На самом деле первая строка немного сложнее xs="$some foo/bar */* $(get_others)".
Если вы запустите этот скрипт в каталоге, содержащем a/b, вы получите -0 foo/bar -0 a/bвместо этого.
Когда я меняю последнюю строку на
echo "$xs_cmd" # note the quotes
Я получаю -0 foo/bar -0 a/b и, прежде всего, что это не то, что я хочу, так как теперь я вызова echoс одним аргументом, и, кроме того, что говорит мне, что расширение происходит раньше, вероятно, в forцикле.
Но я не могу изменить forлинию, потому что
for x in "$xs"; do # note the quotes
заставит цикл повторяться только один раз: -0 foo/bar */*(есть одиночный -0), поэтому добавление этих кавычек не является опцией наверняка.
Теперь, если я вернусь к исходному сценарию и заменим первую строку на
xs="foo/bar '*/*'" # note additional single quotes
Я получаю -0 foo/bar -0 '*/*'(одинарные кавычки не должно быть там).
Кажется, что я пробовал каждую комбинацию кавычек и обратной косой черты звездочек, и я буквально не знаю, что теперь делать.
2 ответа на вопрос
0
AFH
Я использовал ваш оригинальный скрипт, но с одинарными кавычками в первой строке (только), и он работал так, как я думаю, вы хотите ( -0перед каждым путем к файлу): -
xs='foo/bar */*' xs_cmd="" for x in $xs; do xs_cmd="$xs_cmd -0 $x " done echo $xs_cmd
Вероятно, вы обнаружите проблемы, когда будете использовать его, если в любом из путей к файлам есть пробелы. Если это так, измените команду в цикле на: -
xs_cmd="$xs_cmd -0 \"$x\" "
Нет, это все равно выполняет расширение в цикле `for` и выводит` a / b` вместо `* / *`. Другая проблема заключается в том, что первая строка несколько сложнее в реальности; Я обновлю вопрос через минуту.
kirelagin 9 лет назад
0
Я думал, что вы хотите, чтобы это расширилось в цикле `for`. Я протестировал его на Ubuntu 14.04 и получил `-0" foo / bar "-0" dir / file "-0" dir / file "...`
AFH 9 лет назад
0
Возможно, вы захотите прочитать мой вопрос еще раз, особенно ту часть, которая находится прямо перед горизонтальной линейкой, которая дает желаемый результат: расширение _no_ должно быть выполнено; Мне нужно, чтобы все звездочки остались на месте.
kirelagin 9 лет назад
0
ХОРОШО. Я нашел то, что работает. Создайте первую строку `xs =" foo / bar @ / @ "`, затем после цикла `for` добавьте строку` xs_cmd = $ (echo $ xs_cmd | sed "s / @ / \ * / g") `. Если вы не можете найти такой символ, как `@`, которого нет ни в одном из имен файлов, используйте `xs =" foo / bar /// "` и `xs_cmd = $ (echo $ xs_cmd | sed" s - /// - \ * / \ * - г ")`. Сначала я предложил использовать `@`, так как для других строк проще сделать звездочки.
AFH 9 лет назад
0
Итак, теперь у меня есть `xs_cmd`, который представляет собой строку с некоторыми звездочками. Как передать это команде (`echo` в моем примере)? `echo $ xs_cmd` выполнит расширение. `echo" $ xs_cmd "` вызовет `echo` с одним аргументом.
kirelagin 9 лет назад
0
Я имею в виду, что программирование оболочки действительно безумно. Я мог бы написать эту программу на любом другом языке за две минуты и заставить ее работать всего за одну попытку. Но теперь я действительно хочу знать, как написать это в оболочке!
kirelagin 9 лет назад
0
Поскольку вы боретесь с расширением имени файла, почему бы не отключить его в этом контексте с помощью `set -f` и впоследствии восстановить его с помощью` set + f`?
AFH 9 лет назад
0
Ах, конечно! Ну, я бы классифицировал это как обходной путь, а не как истинное решение (потому что мне все еще интересно, как это сделать напрямую), но это работает. Спасибо!
kirelagin 9 лет назад
0
Я думал о вашем комментарии, и я не считаю, что это обходной путь. Ваш сценарий не выполняется, потому что звездочки расширяются, когда вы этого не хотите, поэтому остановка их расширения в неподходящее время является решением, потому что это именно то, что пытаются сделать другие предложения.
AFH 9 лет назад
0
0
oxij
Depending on what you're trying to achieve, your either need to quote these */*:
xs="foo/bar '*/*'" #! xs_cmd="" for x in $xs ; do xs_cmd="$xs_cmd -0 $x " done echo $xs_cmd eval echo $xs_cmd eval "echo $xs_cmd"
or use arrays, or both:
xs=("foo/bar" "*/*") #! xs_cmd="" for x in "$"; do xs_cmd="$xs_cmd -0 '$x' " #! done echo "$xs_cmd" eval "echo $xs_cmd"
Как упоминалось в моем вопросе, ваше первое предложение приводит к следующему выводу: `-0 foo / bar -0 '* / *'`, что означает, что кавычки буквально передаются программе. Ваше второе предложение приводит к `-0 'foo / bar' -0 'a / b'`, который _both_ передает кавычки в программу ** и ** выполняет расширение, в то время как мне не нужно ни того, ни другого.
kirelagin 9 лет назад
0