Bash脚本:每行抓取第一项,投入阵列

时间:2016-08-18 18:25:20

标签: oracle bash shell awk grep

我对编写Bash脚本的世界还很陌生,我需要一些指导。我已经开始编写一个工作脚本,到目前为止一直很好。但是,我现在处于需要收集数据库名称的部分。名称实际上存储在一个文件中,我可以grep它们。

我给出的命令是cat /etc/oratab,它产生这样的东西:

# This file is used by ORACLE utilities.  It is created by root.sh
# and updated by the Database Configuration Assistant when creating
# a database.

# A colon, ':', is used as the field terminator.  A new line terminates
# the entry.  Lines beginning with a pound sign, '#', are comments.
#
# The first and second fields are the system identifier and home
# directory of the database respectively.  The third filed indicates
# to the dbstart utility that the database should , "Y", or should not,
# "N", be brought up at system boot time.
#
OEM:/software/oracle/agent/agent12c/core/12.1.0.3.0:N
*:/software/oracle/agent/agent11g:N
dev068:/software/oracle/ora-10.02.00.04.11:Y

dev299:/software/oracle/ora-10.02.00.04.11:Y

xtst036:/software/oracle/ora-10.02.00.04.11:Y

xtst161:/software/oracle/ora-10.02.00.04.11:Y
dev360:/software/oracle/ora-11.02.00.04.02:Y
dev361:/software/oracle/ora-11.02.00.04.02:Y
xtst215:/software/oracle/ora-11.02.00.04.02:Y
xtst216:/software/oracle/ora-11.02.00.04.02:Y
dev298:/software/oracle/ora-11.02.00.04.03:Y
xtst160:/software/oracle/ora-11.02.00.04.03:Y

我转过身来写grep ":/software/oracle/ora" /etc/oratab所以它可以抓住我需要的一切,即10个数据库。不是最优雅的方式,但它得到我需要的东西:

dev068:/software/oracle/ora-10.02.00.04.11:Y
dev299:/software/oracle/ora-10.02.00.04.11:Y
xtst036:/software/oracle/ora-10.02.00.04.11:Y
xtst161:/software/oracle/ora-10.02.00.04.11:Y
dev360:/software/oracle/ora-11.02.00.04.02:Y
dev361:/software/oracle/ora-11.02.00.04.02:Y
xtst215:/software/oracle/ora-11.02.00.04.02:Y
xtst216:/software/oracle/ora-11.02.00.04.02:Y
dev298:/software/oracle/ora-11.02.00.04.03:Y
xtst160:/software/oracle/ora-11.02.00.04.03:Y

所以,如果我想获取名称,例如dev068或xtst161,我该怎么办?我认为我需要对这个项目进行前进,将它们存储在一个数组中。如文档中所述,冒号是字段终止符。我怎么能把它鞭在一起所以我有一个数组,如:

dev068
dev299
xtst036
xtst161
dev360
dev361
xtst215
xtst216
dev298
xtst160

我觉得我可能在这里要求太多帮助,但我真的很茫然。我很乐意澄清是否需要。

4 个答案:

答案 0 :(得分:2)

使用awk更加简单:

awk -F: -v key='/software/oracle/ora' '$2 ~ key{print $1}' /etc/oratab

dev068
dev299
xtst036
xtst161
dev360
dev361
xtst215
xtst216
dev298
xtst160

要使用以上输出填充BASH数组:

mapfile -t arr < <(awk -F: -v key='/software/oracle/ora' '$2 ~ key{print $1}' /etc/oratab)

检查输出:

declare -p arr
declare -a arr='([0]="dev068" [1]="dev299" [2]="xtst036" [3]="xtst161" [4]="dev360" [5]="dev361" [6]="xtst215" [7]="xtst216" [8]="dev298" [9]="xtst160")'

答案 1 :(得分:1)

我们可以将grep的输出传递给cut实用程序来提取第一个字段,将冒号作为字段分隔符。

然后,假设任何名称中没有空格或全局字符(受word splittingfilename expansion约束),我们可以使用command substitution来运行管道,并通过在括号内指定输出来捕获array中的输出。

names=($(grep ':/software/oracle/ora' /etc/oratab| cut -d: -f1;));

请注意,上面的命令实际上在命令替换输出上使用了单词拆分,将名称拆分为结果数组的单独元素。这就是为什么我们必须确保任何单个数据库名称中都不会出现空格,否则该名称将在内部拆分为数组的单独元素。命令替换输出中我们希望被视为分词分隔符的唯一字符是line feeds,它分隔出来自cut实用程序的每一行输出。

答案 2 :(得分:1)

你也可以使用awk

awk -F: '!/^#/ && $2 ~ /^\/software\/oracle\/ora-/ {print $1}' /etc/oratab

第一个模式排除任何注释掉的行(以#开头)。第二个模式在第二个字段中查找您期望的目录模式。如果满足两个条件,则打印第一个字段,即Oracle SID。 -F:标志将字段分隔符设置为冒号。

使用您的文件:

dev068
dev299
xtst036
xtst161
dev360
dev361
xtst215
xtst216
dev298
xtst160

根据您正在做的事情,您可以进一步细化它并检查最后一个标志是否设置为Y;虽然这确实表示自动启动,但它有时可用于表明数据库根本不活跃。

您可以将结果放入数组:

declare -a DBS=(`awk -F: -v key='/software/oracle/ora' '$2 ~ key{print $1}' /etc/oratab`)

然后引用${DBS[1]}(评估为dev299)等。

答案 3 :(得分:1)

如果您想将它们变成Bash数组:

$ cat > toarr.bash
#!/bin/bash
while read -r line
do
    if [[ $line =~ .*Y$ ]] # they seem to end in a "Y"
    then
        arr[$((i++))]=${line%%:*}
    fi
done < file
echo ${arr[*]} # here we print the array arr
$ bash toarr.bash
dev068 dev299 xtst036 xtst161 dev360 dev361 xtst215 xtst216 dev298 xtst160