Сброс каждой строки команды в отдельную переменную с помощью bash - PullRequest
0 голосов
/ 23 мая 2018

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

lsscsi --transport | grep fc: | grep tape | awk -F" " ' { print $4 } '
/dev/st0
/dev/st1  

Правка - Вот необработанный вывод команд lsscsi:

[1:0:0:0] tape fc:0x50014380032a90b8,0x000001 /dev/st0 
[2:0:0:0] tape fc:0x50014380032a90bb,0x000001 /dev/st1  

Я хочу просто найти способ перенаправить каждую строку предыдущего вывода в новую переменную ($drive0=/dev/st0, $drive1=/dev/st1 и т. Д.).Моя первая попытка выглядела так, и она не работает, потому что все строки сбрасываются в одну и ту же переменную с именем $path_tape:

#!/bin/bash
/usr/bin/lsscsi --transport | grep fc: | grep tape | while read line ; do
    path_tape=$(echo $line | awk -F" " ' { print $4 } ')
done

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

#!/bin/bash
i=0
/usr/bin/lsscsi --transport | grep fc: | grep tape | while read line ; do
    var="path_tape$i"
    ${!var}=$(echo $line |awk -F" " ' { print $4 } ')
    ((i++))
done

Но при выполнении я теперь получаю синтаксическую ошибку:

./test.sh: line 7: =/dev/st0: No such file or directory
./test.sh: line 7: =/dev/st1: No such file or directory

Что мне здесь не хватает?

Ответы [ 2 ]

0 голосов
/ 23 мая 2018

Как насчет этого?

Это будет доступно как переменные среды path_tape0 и path_tape1 в сеансе оболочки

#!/bin/bash
i=0;
/usr/bin/lsscsi --transport | grep fc: | grep tape | while read line ; 
  do
      export "path_tape$i"=$(echo $line |awk ' { print $4 } '); env | grep path_tape ;((i++));
  done
0 голосов
/ 23 мая 2018

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

Я думаю, что лучший способ сделать то, что вы хотите, это использовать mapfile, который превращает строки ввода в массив.Другое имя для mapfile - readarray, вы можете использовать любое из них:

mapfile -t path_tape < <(lsscsi --transport | awk -F" " '/tape fc:/ { print $4 }')
readarray -t path_tape < <(lsscsi --transport | awk -F" " '/tape fc:/ { print $4 }')

Опция -t удаляет символы новой строки из элементов массива.Поскольку у нас нет файла, а вместо вывода команды, в качестве ввода используется <(process substitution).

Теперь path_tape - это массив, к элементам которого можно обращаться, например, "${path_tape[i]}"где i - число.

В качестве бонуса я сократил ваш конвейер, объединив команды grep и awk.Структура сценария awk condition { action }, где условием может быть совпадение с регулярным выражением, как в этом примере.

Проверка его, замена вывода команды файлом:

$ cat file
[1:0:0:0] tape fc:0x50014380032a90b8,0x000001 /dev/st0 
[2:0:0:0] tape fc:0x50014380032a90bb,0x000001 /dev/st1  
$ mapfile -t path_tape < <(cat file | awk -F" " '/tape fc:/ { print $4 }')
$ printf '%s\n' "${path_tape[@]}"
/dev/st0
/dev/st1
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...