shell - повторение цикла для (проверенного) предоставленного числа или диапазона чисел - PullRequest
0 голосов
/ 29 августа 2018

Мне нужно принять ввод от пользователя (то есть «прочитать»).

Этим вводом может быть либо одно положительное число, либо диапазон чисел (в форме X-Y).

Затем мне нужно проверить этот ввод и выполнить итеративный цикл по диапазону чисел (или только один раз в случае только X).

Примеры:

1) Пользователь поставляет: «8» или «8-» Цикл работает только один раз, предоставляя число 8

2) Пользователь поставляет: "13-22"

Цикл запускается 11 раз (с 13 по 22), ссылаясь на число 13.

3) Поставки пользователя: "22-13"

Вероятно, должен вести себя как # 2 выше ... но я открыт для других чистых способов проверки ввода.

До сих пор я работал над следующим, который не очень чистый, полный и даже не на 100% правильный для того, что я просил - но он показывает усилия и идею, к которой я стремлюсь:

echo "line?"; read -r deleteline
case "$deleteline" in
        ''|*[!0-9\-]*)   echo "not a number";;
        [1-9]|[1-9][0-9]*);;
esac


deleteline_lb=$(echo $deleteline|awk -F "-" '{print $1}')
deleteline_ub=$(echo $deleteline|awk -F "-" '{print $2}')

if [ ! $deleteline_lb = "" ] && [ ! "$deleteline_ub" = "" ]; then
        delete_line_count=1
        delete_line_count=$(expr $deleteline_ub - $deleteline_lb)
        if [ $delete_line_count -le 0 ]; then
                delete_line_count=1
        fi
fi

i=1; while [ $i -le $delete_line_count ]; do
  echo $deleteline_lb $i
  i=$(($i + 1))
done

Это должно выполняться в sh, такие вещи, как seq не поддерживаются - так что придерживайтесь методов, совместимых с posix ...


Чтобы уточнить, я собираюсь сделать следующее (псевдокод): 1) принять ввод от пользователя 2) проверить, если ввод находится в форме «#» или «# - #» (диапазон). 3) Выполнить выбранный (произвольный) путь кода на основе правильного / неправильного ввода. 4) Если указан одиночный #, сохраните его в переменной для выполнения будущих операций. 5) Если задан диапазон, сохраните оба числа в переменной, чтобы иметь возможность выполнить операцию от младшего # до более высокого числа. В частности, это будет "(выше #) - (ниже #) + 1". Таким образом, если диапазон был 12-17, то нам нужно выполнить операцию против 12, 6x. (17 - 12 + 1). IOW, 12-17 включительно. 6) Требуется также легко указать, является ли набор данных диапазоном по сравнению с одним числом, чтобы путь кода к каждому из них можно было легко разветвлять.

спасибо за помощь!

UPDATE:

Используя мой основной код, я переработал его (с небольшим вкладом от друга) и в основном придумал это:

            while true;do
                printf "\\delete lines? [e=Exit] ";read -r deleteline
                case "$deleteline" in
                    [Ee])   break;;
                    *)
                    echo "$deleteline" | egrep -q '^[[:digit:]-]*$' 

                    if [ $? -ne 0 ]; then
                       printf "\\n input is not a number.\\n"
                    else
                        delete_range_start=`echo $deleteline|awk -F "-" '{print $1}'` 
                        delete_range_end=`echo $deleteline|awk -F "-" '{print $2}'` 

                        if [ $delete_range_end -lt $delete_range_start ]; then
                            printf "\\n upper range must be higher than lower range.\\n"
                        else
                            if [ "$delete_range_end" = "" ]; then
                                delete_range_end=$delete_range_start
                            elif [ $delete_range_end -gt $lineNumbers ]; then
                                printf "\\Setting range to last entry\\n"
                            fi
                            break
                        fi  
                    fi
                    ;;
                esac

            done

            deleteline=$delete_range_start
            deleteloop=`expr $delete_range_end - $delete_range_start + 1`

            i=1
            while [ $i -le $deleteloop ]; do
                    # Insert all processing code in here
                    i=`expr $i + 1`
            done    

1 Ответ

0 голосов
/ 29 августа 2018

Если у вас есть posix-совместимый awk, попробуйте это:

echo "$userInput" | awk -F- '
  ($1+0==$1&&$2+0==$2){
     for(i=$1;($1<$2?i<=$2:i>=$2);)
       print ($1<$2?i++:i--);
     next
  }
  $1+0==$1{
    print $1;
    next
  }
  $2+0==$2{
    print $2;
    next
  }
  ($1+0!=$1&&$2+0!=$2){
    exit 1
  }'

Скрипт проверяет, являются ли 2 поля (разделенные -) числами. Если это так, он печатает эти числа в порядке возрастания или убывания, в зависимости от того, больше или меньше первое число, чем второе.
Если ввод только один, скрипт просто его печатает.
Если ни одно из полей не является числовым, оно выходит с ненулевым значением.

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

$ cat test.sh
#!/bin/sh
echo -n "range: "
read -r range
validated_input=$(echo "$range" | awk -F- '($1+0==$1&&$2+0==$2){for(i=$1;($1<$2?i<=$2:i>=$2);)print ($1<$2?i++:i--);next}$1+0==$1{print $1;next}$2+0==$2{print $2;next}($1+0!=$1&&$2+0!=$2){exit 1}')
if [ $? -ne 0 ]; then
    echo "Incorrect range" >&2
fi
for i in $validated_input; do
    echo "$i"
done

Примеры:

$ ./test.sh
range: 10-6
10
9
8
7
6
$ ./test.sh
range: 8-
8
$ ./test.sh
range: hello
Incorrect range
...