2013-09-11 3 views
1

У меня есть 2 вопроса о регулярном выражении в выражении bash.
regex in bash выражение

1.Non-жадные Режим

local temp_input='"a1b", "d" , "45"' 
if [[ $temp_input =~ \".*?\" ]] 
then 
    echo ${BASH_REMATCH[0]} 
fi 

В результате

"a1b", "d" , "45" 

В Java

String str = "\"a1b\", \"d\" , \"45\""; 
Matcher m = Pattern.compile("\".*?\"").matcher(str); 
while (m.find()) { 
    System.out.println(m.group()); 
} 

я могу получить результат ниже.

"a1b" 
"d" 
"45" 

Но как я могу использовать не жадный режим в bash?
Я могу понять, почему \ "[^ \"] \ "работает.
Но я не понимаю, почему это \". ?
\»не работают

2.global соответствует

local temp_input='abcba' 
if [[ $temp_input =~ b ]] 
then 
    #I wanna echo 2 b here. 
    #How can I set the global flag? 
fi 

Как я могу получить все матчи
пс:.? Я только хочу использовать регулярное выражение

Что касается второго вопроса. , извините за путаницу.
Я хочу повторить «б» и «б», не считать «Ъ».

Помощь!

+2

Регулярные выражения 'bash' не имеют жадного режима. См. 'Man 7 regex' для того, что поддерживается. – chepner

+0

@chepner Спасибо за помощь. Я также ничего не знаю о не-жадном режиме в конкретном. Я думаю ты прав. –

ответ

3

Для вашего первого вопроса, альтернатива такова:

[[ $temp_input =~ \"[^\"]*\" ]] 

Для вашего второго вопроса, то вы можете сделать это:

temp_input=abcba 
t=${temp_input//b} 
echo "$(((${#temp_input} - ${#t})/1)) b" 

Или для удобства разместить его на функции:

function count_matches { 
    local -i c1=${#1} c2=${#2} 
    if [[ c2 -gt 0 && c1 -ge c2 ]]; then 
     local t=${1//"$2"} 
     echo "$(((c1 - ${#t})/c2)) $2" 
    else 
     echo "0 $2" 
    fi 
} 

count_matches abcba b 

Оба выпускают выходные данные:

2 b 

Обновление:

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

function find_matches { 
    MATCHES=() 
    local STR=$1 RE="($2)(.*)" 
    while [[ -n $STR && $STR =~ $RE ]]; do 
     MATCHES+=("${BASH_REMATCH[1]}") 
     STR=${BASH_REMATCH[2]} 
    done 
} 

Пример:

> find_matches abcba b 
> echo "${MATCHES[@]}" 
b b 

> find_matches abcbaaccbad 'a.' 
> echo "${MATCHES[@]}" 
ab aa ad 
+0

Спасибо за помощь. Извините, что смутил вас. Для второго вопроса, я хочу b и b, а не считать "b". –

+0

Я могу понять, почему работает \ "[^ \"] * \. Но я не понимаю, почему \ ". *? \" Не работает. –

+0

@android_su Вероятно, потому что bash его не реализует, или интерпретирует его по-другому. В строгом смысле интерпретирует '\ '. *? \" 'Я считаю, что bash не ошибается. Функция доступна только в других программах. Я сделал обновление кстати. – konsolebox

2
  1. Вашего регулярное выражение соответствует строке, начиная с первой кавычкой (до ab) и заканчивая последнюю кавычкой (после ef). Это жадно, хотя ваше намерение состояло в том, чтобы использовать не-жадный матч (*?). Кажется, что bash использует регулярное выражение POSIX.2 (проверьте свой man 7 regex), который не поддерживает не жадную звезду Клини.

    Если вы хотите просто "ab", я хотел бы предложить другое регулярное выражение:

    if [[ $temp_input =~ \"[^\"]*\" ]] 
    

    , который явно говорит, что вы не хотите кавычки внутри ваших строк.

  2. Я не понимаю, что вы имеете в виду. Если вы хотите найти все совпадения (и есть два вхождения b здесь), я думаю, вы не сможете сделать это с помощью единственного матча ~=.

+0

Спасибо за помощь. Для первого вопроса я могу понять вашу строку регулярных выражений, но я хочу знать, почему моя работа не работает. второй вопрос, не могли бы вы дать мне хороший способ получить два «б», пожалуйста? Я новичок в битве. –

1

Это мой первый пост, и я очень любитель на баше, так извинения, если я не понял вопрос, но я написал функцию для нежадных регулярных выражений с использованием целиком Баша:

regex_non_greedy() { 
    local string="$1" 
    local regex="$2" 
    local replace="$3" 

    while [[ $string =~ $regex ]]; do 
     local search=${BASH_REMATCH} 
     string=${string/$search/$replace} 
    done 

    printf "%s" "$string" 
} 

Пример вызова:

regex_non_greedy "all cats are grey and green" "gre+." "white" 

Который возвращает:

all cats are white and white