2

У меня проблемы с получением следующего поведения:

input='somestring... --key1 val1 --key2 val2 --key3 val3 somestring...'
output='val1'

Я пытался с помощью:

echo $input | sed -nE 's/.*--key1 (.*) (--.*)$/\1/p' 
#but this gives 'val1 --key2 val2' instead of 'val1' 

По сути, моя проблема в том, что я не знаю, как сказать sed чтобы он соответствовал шаблону в обратном порядке (чтобы --key2 не был записан в \1). Я считаю, что здесь есть простой способ, но я не могу его найти?

изменить: исправить можно было бы использовать:

echo $input | sed -nE 's/.*--key1 ([^(--)]*) (--.*)$/\1/p' 

Но я хотел бы знать, существует ли "лучшее" решение для этого варианта использования?

1 ответ1

1

Это потому что (.*) Слишком жадный.

Perl имеет не жадное соответствие:

perl -nE 'if (/--key1 (.*?) --/) {say $1}' <<< "$input"

Если вы действительно хотите использовать правильный вариант разбора:

eval set -- "$(getopt --long key1:,key2:,key3: -- $input)"   # $input is unquoted!

while :; do
    case "$1" in
        --key1) key1=$2; shift 2;;
        --key2) key2=$2; shift 2;;
        --key3) key3=$2; shift 2;;
        --) shift; break;;
    esac
done

[[ "$output" = "$key1" ]] && echo OK

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .