我目前正在开发一个用于磁带备份的小脚本,我需要该脚本来搜索链接到系统的任何磁带驱动器。
我设法让这部分工作,我们可以看到下面两个磁带机的路径:
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
现在的问题是,有this thread提到了一种增加变量名的方法,所以我尝试调整代码以适应这个解决方案,结果出现了以下几行:
#!/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
我错过了什么?
最佳答案
与其创建带有数字后缀的变量名来“模拟”数组,不如在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
关于linux - 用bash将命令的每一行转储到不同的变量中,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/50490125/