Intereting Posts
Что означает термин «установка» или «установка», когда используется в связи с программным обеспечением Linux? Как я могу искать файлы без определенных расширений в своих именах? Поиск нераспределенного дискового пространства (разделение) Включите параллельный порт и используйте его для последовательной связи (RS-232) Что означает высокая нагрузка с пустым верхним значением? Как избавиться от «Ничего не найдено» при запуске «rm *» udev правило включить подсветку клавиатуры Как пометить предыдущий конец файла, следуя за ним (tail -f / less)? openssl не создает сертификаты с ожидаемой датой истечения срока действия Установка USB-накопителя, который не распознается Нужно ли запускать резервные копии с помощью rsync как пользователя root? * .tar.gz резервное копирование Преобразование загрузки BIOS в UEFI в существующей Linux-установке Как получить код выхода grep, но распечатать все строки? Программный RAID 5 и 6 размер полосы: почему меньше менее эффективно?

подстроки и регулярные выражения

У меня есть строка, содержащаяся в переменной, и я хочу извлечь подстроки, основанные на позиции относительно другой подстроки. Мое решение, похоже, работает, если строка не отправляется в функцию как arg. Я использую оболочку bash.

#!/usr/bin/bash var0="-a check one two three" var1="check" function getsubstr() { echo ${*#*"${2}"} } # this prints 'one two three' which is what I want echo ${var0#*"${var1}"} # this prints '-a one two three', not what I want. getsubstr $var0 

обратите внимание, что, когда я помещаю echo $* в функцию getsubstr он печатает ту же строку, что и $var0 (-> '-a check one two three'), и когда я помещаю echo $2 в функцию getsubstr печатает ту же строку, что и $var1 (-> 'check'). Итак, мне кажется, что я прошу напечатать одну и ту же подстроку в обоих обстоятельствах.

Еще одна загадка заключается в том, что если вместо функции echo ${*#*"${2}"} в функции getsubstr я использую echo ${*%"${2}"*} , я получаю тот же результат.

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

Кстати, я понимаю, что ${*:3} внутри функции getsubstr работает, чтобы вернуть подстроку, которую я хочу, но я пытаюсь понять поведение #*<regexp> и %<regextp>* .

Ваш getsubstr $var0 передает 5 аргументов функции
Кроме того, $ * и $ @ тестируют каждый отдельный $ 1 $ 2 и т. Д. Arg против # patttern

Что касается RegEx в bash : я добавил несколько примеров в конце) .. и btw, '*' – это только специальный символ регулярного выражения, когда он используется в контексте регулярного выражения, т. Е. при использовании = ~
При первом использовании * в ${* , специальное использование asterisk является именем (psuedo) var, которое расширяется до конкатенации всех vars: $ 1 $ 2 $ … и т. Д.
Второе использование звездочки в #*"${2}" означает «$ 2», которому предшествует ничего, не содержащее ничего , должно быть сопоставлено с каждым переданным аргументом $ 1 и т. Д. Отдельно.

Следующий сценарий может помочь с $ @ и $ * (на примере) …

 #!/bin/bash # getsubstr() { echo -n " ${#@} args"; [[ "$1$2$3$4$5$6" == *\ * ]] && echo " (with embedded spaces)" || echo " (no spaces)" echo ' "${*}" '\|"${*}"\| echo ' ${*} '\|${*}\| echo ' "${@}" '\|"${@}"\| echo ' ${@} '\|${@}\| echo ' "${*#*"${2}}" '\|"${*#*"${2}"}"\| echo ' ${*#*"${2}} '\|${*#*"${2}"}\| echo ' "${@#*"${2}}" '\|"${@#*"${2}"}"\| echo ' ${@#*"${2}} '\|${@#*"${2}"}\| echo ' ${*#B} '\|${*#B}\| echo ' "${*#B}" '\|"${*#B}"\| echo ' ${@#B} '\|${@#B}\| echo ' "${@#B}" '\|"${@#B}"\| } var0="a B c " echo echo -n "Passing "; getsubstr "$var0" ; echo echo -n "Passing "; getsubstr $var0 ; echo echo -n "Passing "; getsubstr "$var0" "$var0" ; echo echo -n "Passing "; getsubstr $var0 $var0 ; echo echo exit ################################################################### 

RegEx в bash

 # Regex checks: "=~" uses extended regular expression #+ Parenthesized subexpressions within the regular expression are saved #+ in the array variable BASH_REMATCH #+ $BASH_REMATCH / ${BASH_REMATCH[0]} is the string matching the entire regular expression. #+ ${BASH_REMATCH[n]} is the sub string matching the nth parenthesized subexpression [[ "abcdef" =~ (.)(.)(.) ]] && echo "# $BASH_REMATCH" # abc [[ "abcdef" =~ (.)(.)(.) ]] && echo "# ${BASH_REMATCH[0]}" # abc [[ "abcdef" =~ (.)(.)(.) ]] && echo "# ${BASH_REMATCH[2]}" # b [[ "abcdef" =~ (.)(.)(.) ]] && echo "# ${BASH_REMATCH[@]}" # abc abc 

Обновление с пояснениями

Причина, по которой вы видите этот тип поведения, состоит в том, что $* или даже $@ расширяются до всех позиционных параметров: $1 , $2 и т. Д. Когда вы пытаетесь сделать расширение параметра (PE) на одном из этих двух специальных vars, вы применяют PE к каждому параметру позиции, а не к одной строке.

Выдержка из man bash

$ {параметр # слово}
Удалите соответствующий шаблон префикса. Слово расширяется для создания шаблона так же, как при расширении пути. Если шаблон совпадает с началом значения параметра, то результатом расширения является расширенное значение параметра с кратчайшим шаблоном соответствия ( #'' case) or the longest matching pattern (the случай ##'), удаленный , Если параметр равен @ или *, операция удаления паттерна применяется поочередно по каждому позиционному параметру, а расширение – это результирующий список.

По существу, вы делаете это:

 getsubstr() { tmp=$2 for arg; do printf "%s " ${1#*$tmp} shift done } 

Следующая функция работает, устанавливая $* в temp var $tmp потому что вы теперь применяете PE к обычной переменной один раз.

 getsubstr() { tmp=$* echo ${tmp#*$2} } 

PS

Не используйте function поскольку она не является POSIX и фактически совершенно ненужной, если вы уже используете () после имени вашей функции.

PPS

Это фактически не имеет никакого отношения к регулярным выражениям, а скорее к глобулярным выражениям . Более формально они известны как Расширения параметров