Использовать чтение как подсказку внутри цикла while, управляемого read?

Вы должны знать, что Wine - это не песочница . Программы, работающие под Wine, не ограничиваются Windows API; Теоретически вирус, осведомленный о Wine, может легко обнаружить, что он работает под Wine, и переключиться на использование API хоста (например, Linux), чтобы нанести столько же вреда, сколько вредоносное ПО для Linux.

Самый надежный способ изоляции - полная виртуальная машина. Менее полными (но, возможно, более практичными) способами было бы запустить программу под Wine внутри chroot или контейнера, однако при этом ядро ​​хоста остается открытым.

9
03.08.2018, 11:59
2 ответа

Если я правильно понял, я думаю, что вы хотите в основном перебирать списки значений, а затем readеще одно в цикле.

Вот несколько вариантов, 1 и 2, наверное, самые разумные.

1. Эмулировать массивы строками

Было бы неплохо иметь 2D-массивы, но в Bash это невозможно. Если в ваших значениях нет пробелов, один обходной путь для аппроксимации состоит в том, чтобы вставить каждый набор из трех чисел в строку и разделить строки внутри цикла:

for x in "1 2 3" "4 5 6"; do 
  read a b c <<< "$x"; 
  read -p "Enter a number: " d
  echo "$a - $b - $c - $d ";
done

Конечно, можно использовать и другой разделитель, например. for x in 1:2:3...и IFS=: read a b c <<< "$x".


2. Заменить канал другим перенаправлением на свободный стандартный ввод

Другая возможность состоит в том, чтобы read a b cчитался из другого fd и направлял ввод в этот (это должно работать в стандартной оболочке):

while read a b c <&3; do
    printf "Enter a number: "
    read d
    echo "$a - $b - $c - $d ";
done 3<<EOF
1 2 3
4 5 6
EOF

И здесь вы также можете использовать подстановку процесса, если хотите получить данные из команды:while read a b c <&3;...done 3< <(echo $'1 2 3\n4 5 6')(подстановка процесса — это функция bash/ksh/zsh)


3. Вместо этого брать пользовательский ввод из stderr

Или, наоборот, используя канал, как в вашем примере, но вводите пользовательский ввод readизstderr(fd 2 )вместо stdin, откуда идет канал:

echo $'1 2 3\n4 5 6' |
while read a b c; do 
    read -u 2 -p "Enter a number: " d
    echo "$a - $b - $c - $d ";
done

Чтение из stderrнемного странно, но на самом деле часто работает в интерактивном сеансе. (Вы также можете явно открыть /dev/tty, предполагая, что вы действительно хотите обойти любые перенаправления, это то, что такие вещи, как less, используют для получения ввода пользователя, даже если данные передаются ему.)

Хотя использование stderrтаким образом может работать не во всех случаях, и если вы используете какую-то внешнюю команду вместо read, вам, по крайней мере, потребуется добавить к команде несколько перенаправлений.

Также см. Почему моя переменная локальна в одном цикле while read, но не в другом похожем цикле? по некоторым вопросам, касающимся ... | while.


4. Разрезать части массива по мере необходимости

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

data=(1 2 3 
      4 5 6)

n=3
for ((i=0; i < "${#data[@]}"; i += n)); do
    a=( "${data[@]:i:n}" )
    read -p "Enter a number: " d
    echo "${a[0]} - ${a[1]} - ${a[2]} - $d "
done

Вы также можете назначить ${a[0]}и т. д. на a, bи т. д., если вам нужны имена для переменных, но Zsh сделает это намного лучше .

12
27.01.2020, 20:06

С помощью zshвы можете вместо этого написать:

for a b c (
  1 2 3
  4 5 6
  'more complex' $'\n\n' '*** values ***'
) {
  read 'd?Enter a number: '
  do-something-with $a $b $c $d
}

Для двумерных массивов см. также оболочку ksh93:

a=(
  (1 2 3)
  (4 5 6)
  ('more complex' $'\n\n' '*** values ***')
)
for i in "${!a[@]}"; do
  read 'd?Enter a number: '
  do-something-with "${a[i][0]}" "${a[i][1]}" "${a[i][2]}" "$d"
done
2
27.01.2020, 20:06

Теги

Похожие вопросы