2011-01-28 2 views
2

Я пытаюсь разрешить строки, которые имеют пробелы в них, считаться целыми строками, а не анализироваться. Это то, что я хотел бы, чтобы произошло:Подсчет пробелов в аргументах в KSH?

$ ksh program.ksh "what up" 
File 'what up' not found. 

И это то, что я получаю:

$ ksh program.ksh "what up" 
File 'what' not found. 
File 'up' not found. 

Это код, который я пытался сделать работу:

wflag=false 
cflag=false 

while getopts "cw" opt; do 
    case "$opt" in 
    c) 
     cflag=true 
     ;; 
    w) 
     wflag=true 
     ;; 
    /?) 
     ;; 
    esac 
done 

Проблема заключается в том, что 1) Я пробую что-то выше, как ksh program.ksh "what up", и 2) когда я пробую что-то вроде ksh program.ksh "-w -c". Второй - самый запутанный, так как когда я печатаю wflag и cflag, они оба верны. Не следует ли обрабатывать здесь "-w -c"? Кажется, что ядро ​​(это ядро, выполняющее здесь работу?) Анализирует это, хотя это именно то, чего я не хочу; Я хочу, чтобы он рассматривался как строка с пробелом. Я прочитал WordSplitting и ((статья о Аргументах, не позволяла мне публиковать его, хотя)), и думаю Я понимаю. Ясно, что я должен что-то упускать, или вообще не понимаю его: P

Мой инстинкт говорит мне, что что-то происходит с getopts, который автоматически избавляется от любых пробелов. Я пробовал $(opt) вместо "$opt", а также с фигурными фигурными скобками и/или одинарными кавычками (я уверен, что одиночные кавычки не будут работать, хотя). Увы, нет сигары.

Любая помощь будет принята с благодарностью и благодарит вас за чтение этой стены.

ответ

2

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

#!/bin/ksh 
wflag=false 
cflag=false 

# the first colon means suppress error messages 
# the colon after the x means that -x requires an argument 
while getopts ":cwx:" opt 
do 
    echo "opt $opt" 
    case "$opt" in 
     c) 
      cflag=true 
      ;; 
     w) 
      wflag=true 
      ;; 
     x) 
      echo "x is an option, $OPTARG is its argument" 
      ;; 
     \?) 
      echo "invalid option" 
      ;; 
     *) 
      echo "missing argument" 
      ;; 
    esac 
done 
echo "cflag $cflag" 
echo "wflag $wflag" 

Теперь давайте назовем это несколькими способами:

$ ./script.ksh -c 
opt [c] 
cflag true 
wflag false 

Fine.

$ ./getoptstest.ksh -c -w 
opt [c] 
opt [w] 
cflag true 
wflag true 

Также отлично.

$ ./getoptstest.ksh -cw 
opt [c] 
opt [w] 
cflag true 
wflag true 

Все еще хорошо, но наш ответ предвещается.

$ ./getoptstest.ksh '-c -w' 
opt [c] 
opt [?] 
invalid option 
opt [?] 
invalid option 
opt [w] 
cflag true 
wflag true 

Теперь мы куда-то попадаем. man страница Korn оболочки говорит:

Ведущий: в строка_опциях вызывают getopts хранить букву недопустимый параметр в OPTARG и множество VNAME к? для неизвестной опции и до: когда обязательный аргумент параметра отсутствует - ing. В противном случае getopts выводит сообщение об ошибке.

Как вы можете видеть из примера до этого последнего, вы можете запускать параметры вместе, как в -cw.Когда вы передаете такой вариант, как '-c -w', getopts видит его как -c-space и -w. Таким образом, в дополнение к двум недействительных опций (-- и -space) он видит как -c и -w, и именно поэтому оба флаги становятся установлены. Без ведущего толстой кишки (который является способом оригинального сценарий размещен в вопросе), вы должны получать сообщения об ошибках, подобное этим:

./script.ksh: - : unknown option 
./script.ksh: --: unknown option 

Если вы присмотритесь, то заметите, предательское пространство и дополнительный тир ,

Прискорбно, что страница man не обсуждает возможность использования аргументов getopts для обработки аргументов, передаваемых отдельно или сгруппированных вместе.

Я не уверен, что я понимаю, что или если есть проблема с вашим примером ksh program.ksh "what up".

Попробуйте мой модифицированный скрипт с этими параметрами и аргументами, чтобы увидеть, как работает его работа.

./script.ksh -x 
./script.ksh -x foo 
./script.ksh -z 
./script.ksh -c bar -w 

Это последнее непросто. Когда аргумент, который не начинается с тире, найден, и предыдущий параметр не принимает аргумент, getopts останавливает обработку, а остальные аргументы остаются на месте. Вы можете использовать shift $(($OPTIND - 1)) после цикла while, и тогда вы сможете получить доступ к остальным позиционным параметрам обычным способом.

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

+0

Благодарим вас за такой ясный и полезный ответ. К сожалению, 'getopts' не поддерживает длинные варианты, я думаю, мне, возможно, придется найти другой способ этого. Я попытаюсь, возможно, хранить все аргументы в массиве и обрабатывать их по одному. Спасибо еще раз за помощь! – Fred

+0

Если вы используете ksh93, его встроенный 'getopts' имеет расширения, позволяющие использовать длинные параметры. – jilles

+0

@Alex: Вы должны знать, что @jilles прокомментировал, что в ksh93 'getopts' разрешает длинные варианты. Он не упоминается на официальной странице 'man' (http://www2.research.att.com/sw/download/man/man1/ksh.html), но он задокументирован в' getopts -man'. Однако, ' bloat'. –

Смежные вопросы