Обработка аргументов в скрипте для модифицированной функции поиска?

237
Stilez

Я использую FreeBSD, и я понимаю и использую эту -pruneопцию, findчтобы предотвратить спуск команды в подкаталог. Но я нахожу необходимый синтаксис очень неуклюжим и неловким. Это также не предотвращает появление самого обрезанного режиссера, что исправимо, но раздражает.

Я хотел бы создать короткий скрипт / псевдоним, который имеет эффект добавления нового -noenterаргумента к findкоманде, если он дан перед любыми другими основными цветами (для простоты).

Цель состоит в том, чтобы я мог напечатать любой из:

  • find -xs /dir -noenter '$*' -name '*.conf' -ls
  • find -x -s /dir -noenter '$*' -name '*.conf' -ls

и он преобразует аргументы и выполнит:

  • /usr/bin/find -xs /dir \( -name '$*' -prune -or \( -name '*.conf' -and ! \( -type d -and -name '$*' \) \) \) -ls
  • /usr/bin/find -x -s /dir \( SNIPPED \) -ls

но я также могу набрать как обычно любую обычную команду "find", и она будет прозрачно передана /usr//bin/findдля выполнения.

По логике сценарий должен идентифицировать первый аргумент после имени dir, а затем проверить:

  • ... равный -noenterи сопровождаемый как минимум еще двумя аргументами (в этом случае я знаю, как построить аргумент, на который мне нужно перейти /usr/bin/find, зная, какие аргументы были до / после него); или же
  • ... равно, -noenterно не сопровождается, по крайней мере, еще 2 аргументами (= ошибка); или же
  • ... что-либо еще или dir было последним аргументом или не было найдено (= передать все исходные аргументы /usr/bin/findнеизменному).

Я могу сделать все это, кроме одной вещи - как мне кодировать ту часть сценария, которая проверяет argv, чтобы определить, какой номер arg (если есть) является dirаргументом?

Мой выбор оболочки shдля сценариев.

3

1 ответ на вопрос

1
gmelis

Если вам нужно проверить наличие и местоположение определенного аргумента, все, что вам нужно сделать, - это проанализировать командную строку и проверить каждый аргумент на соответствие вашему «ожидаемому» значению. Итак, вам нужно проверить каждый аргумент для значения, -noenterа затем напечатать строку с указанием позиции и имени переменной -noenter:

for i in `seq 1 $#`; do ref=`eval "echo \\$$i"` if [ $ref == '-noenter' ]; then echo "arg $i is $ref"; break; fi done 

Теперь то же самое, только позиция аргумента -noenterсохраняется в $mitsosи позиция аргумента до этого в $mary:

for i in `seq 1 $#`; do ref=`eval "echo \\${$i}"` if [ $ref == '-noenter' ]; then mitsos=$i eva=$(($i-1)) mary=`eval "echo \\${$eva}"` break fi done 

и теперь $mitsosимеет позицию -noenterили нет значения и $maryзначение аргумента, предшествующего -noenter. На этом этапе, если $maryу /dirвас есть значение, которое вы знаете следующим аргументом, -noenterи вы можете продолжить реализацию find, в противном случае вы используете версию системы или выводите сообщение об ошибке. Наконец, если вы не заботитесь о позиции, -noenterвы можете пропустить строку mitsos=$i.

Спасибо за понимание того, что я хотел! Ответ не совсем правильный, хотя. Предполагается, что -noenter является допустимым в любой позиции и просто ищет его, но это неверное предположение (`find -x -noenter .....` должно быть ошибкой). Надо проверять arg после "dir" конкретно, как мне кажется? Я, наверное, могу понять это из того, что вы написали, так что это очень близко. Вы хотите отредактировать ответ, чтобы я мог его принять, или? Stilez 6 лет назад 0
Это не проблема, потому что в этом случае у вас будет переменная с * position * из `-noenter` или без переменной. Итак, вы можете проверить значение переменной `$ eva`, где` eva = $ (($ mitsos-1)) `и если аргумент в позиции` $ eva` не равен `dir`, вы продолжите реализацию в противном случае вы используете систему. Я отредактирую ответ, чтобы отразить это. gmelis 6 лет назад 0
Такого рода работы. Я полагаю, учитывая его собственный скрипт / мод команды, неправильный вызов может быть оставлен как крайний случай на данный момент :) Я не хотел бы передавать его другим, чтобы использовать, хотя и без дополнительной проверки правильности синтаксиса, но это просто мои чувства :) Stilez 6 лет назад 0
Метод правильный, но я только что обнаружил, что eval неверен. не обрабатывает несколько пробелов или> = 10 аргументов. Основываясь на вашем, они решают следующие проблемы: `eval 'echo" $ {' $ i '} "'` (output) или `eval 'value =" $ {' $ i '} "'` (assignment). Примечание: окончание + перезапуск кавычек для включения значения $ i вместо обратной косой черты + многократного повторения. По-прежнему не обрабатывает двойные оболочки в командной строке, например `\ (` или `|`, не уверен, что с этим можно сделать. Кредит - все ваше, но если это легко, вы можете обновить, чтобы исправить, или, по крайней мере, обновить, чтобы заметить исключения, так что другие получают лучший результат, если они используют этот ответ? Stilez 6 лет назад 0
Я обновил ответ для более чем 9 аргументов; Вы можете просто использовать фигурные скобки, если не используете одинарные кавычки, что иногда может быть утомительным. Побеги, вероятно, станут еще большей проблемой, и, скорее всего, «труба» - нарушитель соглашения, но я посмотрю, смогу ли я найти способ обойти первое, по крайней мере. gmelis 6 лет назад 0
Я полагаю, что есть 2 аспекта - получить arg в переменную, основанную на его числовом индексе, а затем безопасно перекомпилировать для передачи другой функции в качестве arg. Судя по вашим подсказкам, они сработали очень хорошо: `eval 'vraw =" $ {' $ i '} "'` чтобы получить его в переменной. Я полагал, что реквизиты проще использовать с одинарными, а не с двойными кавычками, и просто исправить встроенные одинарные кавычки, если таковые имеются (следовательно, почти нет необходимости обрабатывать пробелы / нечетные символы и т. Д.). Я придумал это: `vquoted =" '$ (printf "$ vraw" | sed "s /' / '\"' \ "'/ g")' "` - попробуйте. Интересно, что цитирование не влияет на параметры, по-видимому: (`ls '-lt' '/'` в порядке) => безопасно для всех аргументов. Stilez 6 лет назад 0

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