RegEx в bash-скрипте (для цикла) - PullRequest
2 голосов
/ 19 сентября 2010

Я хочу проанализировать аргументы, данные скрипту оболочки, используя цикл for.Теперь, предполагая, что у меня есть 3 аргумента, что-то вроде for i in $1 $2 $3 должно выполнить эту работу, но я не могу предсказать количество аргументов, поэтому я хотел использовать RegEx для диапазона и $ # в качестве номера последнего аргумента.Я не знаю, как использовать эти RegEx 'в цикле for, я пробовал что-то вроде for i in $[1-$#], который не работает.Цикл выполняется только 1 раз, и вычисляется 1 - $ #, а не используется как RegEx.

Ответы [ 3 ]

7 голосов
/ 19 сентября 2010

Basic

Цикл for по умолчанию будет циклически перебирать аргументы командной строки, если вы не укажете предложение in:

for arg; do
    echo "$arg"
done

Если вы хотитебудьте явными, вы можете получить все аргументы как "$@".Вышеприведенный цикл эквивалентен:

for arg in "$@"; do
    echo "$arg"
done

со страницы руководства bash:

Специальные параметры

$@ - Расширение до позиционных параметров, начинаяот одного.Когда раскрытие происходит в двойных кавычках, каждый параметр раскрывается в отдельное слово.То есть "$@" эквивалентно "$1" "$2" ....Если расширение в двойных кавычках происходит внутри слова, расширение первого параметра объединяется с начальной частью исходного слова, а расширение последнего параметра объединяется с последней частью исходного слова.Если позиционные параметры отсутствуют, "$@" и $@ расширяются до нуля (т. Е. Они удаляются).

Advanced

Для обработки аргументов в тяжелых условиях, getopt + shift это путь.getopt предварительно обработает командную строку, чтобы дать пользователю некоторую гибкость в определении аргументов.Например, он расширится -xzf в -x -z -f.После всех флагов добавляется аргумент --, который отделяет флаги от имен файлов;это позволяет вам запустить cat -- -my-file, чтобы отобразить содержимое -my-file без перестановок на начальном тире.

Попробуйте этот шаблонный код для размера:

#!/bin/bash

eval set -- "$(getopt -o a:bch -l alpha:,bravo,charlie,help -n "$0" -- "$@")"

while [[ $1 != -- ]]; do
    case "$1" in
      -a|--alpha)
        echo "--alpha $2"
        shift 2
        ;;

      -b|--bravo)
        echo "--bravo"
        shift
        ;;

      -c|--charlie)
        echo "--charlie"
        shift
        ;;

      -h|--help)
        echo "Usage: $0 [-a ARG] [-b] [-c]" >&2
        exit 1
        ;;
    esac
done
shift

Обратите внимание, что каждый параметримеет короткий длинный эквивалент, например, -a и --alpha.Флаг -a принимает аргумент, поэтому он указан как a: и alpha: в вызове getopt, и имеет shift 2 в конце своего регистра.

1 голос
/ 19 сентября 2010

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

for ((i=1; i<=$#; i++))
do
    echo "${@:i:1}"
done

но синтаксис for arg, который показал Джон Кугельман, гораздо предпочтительнее. Однако бывают случаи, когда нарезка массивов полезна. Кроме того, в этой версии, как и у Джона, массив аргументов остается без изменений. Использование shift отбрасывает его элементы.

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

0 голосов
/ 19 сентября 2010

Я предлагаю вместо этого сделать что-то еще:

while [ -n "$1" ] ; do
  # Do something with $1
  shift
  # Now whatever was in $2 is now in $1
done

Ключевое слово shift перемещает содержимое $ 2 в $ 1, $ 3 в $ 2 и т. Д. Pp.

Допустим, аргументы где:

a b c d

После shift аргументы теперь:

b c d

С помощью цикла while вы можете анализировать произвольное количество аргументов и даже выполнять следующие действия:

while [ -n "$1" ] ; do
  if [ "$1" = "-f" ] ; then
    shift
    if [ -n "$1" ] ; then
      myfile="$1"
    else
      echo "-f needs an additional argument"
    end
  fi
  shift
done

Представьте аргументы как массив, а $ n как индексы в этом массиве. shift удаляет первый элемент, поэтому индекс 1 теперь ссылается на элемент, который был с индексом 2 до shift. Я надеюсь, вы понимаете, что я хочу сказать.

...