Как получить строку до цикла в Bash?

Я работаю над сценарием сжатия файлов. Я хочу сделать "пока цикл", пока содержимое переменной не соответствует шаблону. Скрипт использует zenity. Это основная часть:

part="0"
pattern="^([0-9]{1}[0-9]*([km])$"
until `grep -E "$pattern" "$part"` ; do
    part=$(zenity --entry \
    --title="Zip the file" \
    --text "Choose the size of divided parts:
(0 = no division, *m = *mb, *k = *kb)" \
    --entry-text "0");

    if grep -E "$pattern" "$part" ; then
        zenity --warning --text "Wrong text entry, try again." --no-cancel;
    fi
done

Я хочу, чтобы он принимал строку, содержащую цифры, оканчивающиеся на "k" или "m" (но не оба), и не принимал строку, начинающуюся с "0".

Шаблон в порядке?

2 ответа

Решение
$ grep -w '^[1-9][0-9]*[km]$' <<< 45k
45k
$ grep -w '^[1-9][0-9]*[km]$' <<< 001023m
$ grep -w '^[1-9][0-9]*[km]$' <<< 1023m
1023m

Не забывайте <<< в вашем выражении вы не grep'ing файл, а строка. Чтобы быть более совместимым с POSIX, вы также можете использовать:

echo 1023m | grep -w '^[1-9][0-9]*[km]$'

Но это некрасиво.

Редактировать:

Более длинный пример:

initmessage="Choose the size of divided parts:\n(0 = no division, *m = *mb, *k = *kb)"
errmessage="Wrong input. Please re-read carefully the following:\n\n$initmessage"

message="$initmessage"

while true ; do
    part=$(zenity --entry \
         --title="Zip the file" \
         --text "$message")
    if grep -qw '^[1-9][0-9]*[km]$' <<< "$part" ; then
         zenity --info --text 'Thank you !'
         break
    else
        message="$errmessage"
    fi
done

Кроме того, это не имеет прямого отношения к вопросу, но вы можете взглянуть на Yad, который делает то же самое, что и Zenity, но имеет больше возможностей. Я часто использовал его, когда мне приходилось писать скрипты на Bash, и нашел его гораздо более полезным, чем Zenity.

Вы не хотите обратных цитат в until линия. Вы могли бы написать:

until grep -E "$pattern" "$part"
do
    ...body of loop...
done

Или вы можете добавить аргументы grep подавить вывод (или отправить вывод /dev/null). Как написано, скрипт пытается выполнить вывод grep команда и использовать статус успеха / неудачи этого (не grep per se) как указание, продолжать ли цикл или нет.

Кроме того, ваш шаблон требует некоторой работы. Это:

pattern="^([0-9]{1}[0-9]*([km])$"

Там есть непревзойденная открытая скобка. Мне также кажется, что он пытается разрешить ведущий ноль. Вы, вероятно, хотите:

pattern='^[1-9][0-9]*[km]$'

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


Я просто хочу проверить, называется ли моя переменная part хорошо сформирован после записи в диалоге ввода Zenity. Я только что понял, что grep нужен файл, но мой part переменная, инициализированная в этом скрипте Как теперь ладить?

В bash, вы можете использовать <<< оператор для перенаправления из строки:

until grep -E "$pattern" <<< "$part"

В большинстве других оболочек вы написали бы:

until echo "$part" | grep -E "$pattern"

Это также работает в bash, конечно.

Другие вопросы по тегам