shell 如何将一个输出中的某一行添加到另一个输出中的某一行?

dsekswqp  于 2023-04-07  发布在  Shell
关注(0)|答案(4)|浏览(179)

我有一个输出问题。
所以我有一个命令的输出。

$ sudo /opt/MegaRAID/MegaCli/MegaCli64 -LdPdInfo -a0

Name               : Virtual_Disk0  
RAID Level         : 1 
State              : Optimal  
Number Of Drives   : 2  

Name               : Virtual_Disk1  
RAID Level         : 5 
State              : Optimal  
Number Of Drives   : 6  

Name               : Virtual_Disk2  
RAID Level         : 0 
State              : Optimal  
Number Of Drives   : 2

我有另一个命令的第二个输出。

$ sudo /opt/MegaRAID/MegaCli/MegaCli64 -LdPdInfo -a0 \
> | xargs \
> | sed -r 's/(Slot Number:)(\s[0-9]+)/\2,/g' \
> | sed 's/(Target Id: .)/Physical Drives ids:/g'

Virtual Drive: 0 Physical Drives ids:  0,  1,
Virtual Drive: 1 Physical Drives ids:  2,  3,  4,  5,  6,  7,
Virtual Drive: 2 Physical Drives ids:  8,  9,

因此,我想合并2个输出。虚拟磁盘#末尾的数字必须与虚拟驱动器之后的第一个数字相匹配:#
所以,我希望它看起来像这样:

Name               : Virtual_Disk0  
RAID Level         : 1 
State              : Optimal  
Number Of Drives   : 2  
Virtual Drive: 0 Physical Drives ids:  0,  1,

Name               : Virtual_Disk1  
RAID Level         : 5 
State              : Optimal  
Number Of Drives   : 6  
Virtual Drive: 1 Physical Drives ids:  2,  3,  4,  5,  6,  7,

Name               : Virtual_Disk2  
RAID Level         : 0 
State              : Optimal  
Number Of Drives   : 2 
Virtual Drive: 2 Physical Drives ids:  8,  9,

条目始终匹配,并且它们的顺序相同。
我试过这个:

$ sudo /opt/MegaRAID/MegaCli/MegaCli64 -LdPdInfo -a0 ; \
> sudo /opt/MegaRAID/MegaCli/MegaCli64 -LdPdInfo -a0 | \
> xargs \
> | sed -r 's/(Slot Number:)(\s[0-9]+)/\2,/g' \
> | sed 's/(Target Id: .)/Physical Drives ids:/g'

Name               : Virtual_Disk0  
RAID Level         : 1 
State              : Optimal  
Number Of Drives   : 2  

Name               : Virtual_Disk1  
RAID Level         : 5 
State              : Optimal  
Number Of Drives   : 6  

Name               : Virtual_Disk2  
RAID Level         : 0 
State              : Optimal  
Number Of Drives   : 2 
Virtual Drive: 0 Physical Drives ids:  0,  1,
Virtual Drive: 1 Physical Drives ids:  2,  3,  4,  5,  6,  7,
Virtual Drive: 2 Physical Drives ids:  8,  9,
nnt7mjpx

nnt7mjpx1#

在我的环境中模拟MegaCli64输出:

$ cat mega1.out
Name               : Virtual_Disk0
RAID Level         : 1
State              : Optimal
Number Of Drives   : 2

Name               : Virtual_Disk1
RAID Level         : 5
State              : Optimal
Number Of Drives   : 6

Name               : Virtual_Disk2
RAID Level         : 0
State              : Optimal
Number Of Drives   : 2

$ cat mega2.out
Virtual Drive: 0 Physical Drives ids:  0,  1,
Virtual Drive: 1 Physical Drives ids:  2,  3,  4,  5,  6,  7,
Virtual Drive: 2 Physical Drives ids:  8,  9,

一个awk的想法:

awk '
FNR==NR             { drives[$3] = $0; next }                  # 1st file: use 3rd field as index for storing entire line
$NF~/^Virtual_Disk/ { if (match($NF,/[0-9]+$/))                # 2nd file: last field starts with "Virtual_Disk"; look for number on end of last field and if found ...
                         driveno = substr($NF,RSTART,RLENGTH)  # extract said number
                    }
1                                                              # 2nd file: print current line
/^Number Of Drives/ { if (driveno in drives)                   # 2nd file: line starts with "^Number Of Drives"; if we have a matching record in the drives[] array then ...
                         print drives[driveno]                 # print said line to stdout and ...
                      driveno=""                               # clear our variable
                    }
' <(cat mega2.out) <(cat mega1.out)                            # NOTE: process 2nd set of MegaCli64 output *first*

这产生:

Name               : Virtual_Disk0
RAID Level         : 1
State              : Optimal
Number Of Drives   : 2
Virtual Drive: 0 Physical Drives ids:  0,  1,

Name               : Virtual_Disk1
RAID Level         : 5
State              : Optimal
Number Of Drives   : 6
Virtual Drive: 1 Physical Drives ids:  2,  3,  4,  5,  6,  7,

Name               : Virtual_Disk2
RAID Level         : 0
State              : Optimal
Number Of Drives   : 2
Virtual Drive: 2 Physical Drives ids:  8,  9,

在OP的实际环境中,他们会希望进行以下更改:

# replace this:

' <(cat mega2.out) <(cat mega1.out)

# with this:

' <(sudo /opt/MegaRAID/MegaCli/MegaCli64 -LdPdInfo -a0 | xargs | sed ... | sed ... ) <(sudo /opt/MegaRAID/MegaCli/MegaCli64 -LdPdInfo -a0)

**注意:**我只是复制了OP提供的MegaCli64命令和输出;OP将需要验证这些命令和/或根据需要进行编辑

bjp0bcyl

bjp0bcyl2#

早上好。

$ sudo /opt/MegaRAID/MegaCli/MegaCli64 -LdPdInfo -a0 ; \

> sudo /opt/MegaRAID/MegaCli/MegaCli64 -LdPdInfo -a0 | \
> xargs \
> | sed -r 's/(Slot Number:)(\s[0-9]+)/\2,/g' \
> | sed 's/(Target Id: .)/Physical Drives ids:/g'

在一行的末尾添加一个反斜杠来隐藏换行符并不会合并单独命令的输出,它只是一个很长的文本行,解析器仍然用分号将它们分隔为完全独立的操作。
正如Charles和艾德所指出的,您的第二个命令与第一个命令相同,不可能是正确的。我怀疑您的第二个命令(通过管道传输到xargs的命令)是复制/粘贴错误。请更正。
也就是说,有几个人已经建议使用<(cmd1) <(cmd2)结构,我也推荐使用它。
作为另一个示例,由于我将您的输出保存到filef2中,因此我将使用一个非常冗余的UUoC来模拟<(...)的-

mapfile -t drive < <(cat f2)
while IFS=@ read -d@ block || [[ -n "$block" ]]
do echo "${block/\n/}${drive[ndx++]}"
done < <( sed 's/^$/@/' <(cat file) )

其输出

Name               : Virtual_Disk0
RAID Level         : 1
State              : Optimal
Number Of Drives   : 2
Virtual Drive: 0 Physical Drives ids:  0,  1,

Name               : Virtual_Disk1
RAID Level         : 5
State              : Optimal
Number Of Drives   : 6
Virtual Drive: 1 Physical Drives ids:  2,  3,  4,  5,  6,  7,

Name               : Virtual_Disk2
RAID Level         : 0
State              : Optimal
Number Of Drives   : 2
Virtual Drive: 2 Physical Drives ids:  8,  9,

不过,awk解决方案更好,我最喜欢Cyrus简单优雅的sed

编辑

$: sed /^Number/R<(echo "$phyDrives3") <(echo "$megaCliVD3")
Name               : Virtual_Disk0
RAID Level         : 1
State              : Optimal
Number Of Drives   : 2
Physical Drives    : 0,  1,
Name               : Virtual_Disk1
RAID Level         : 5
State              : Optimal
Number Of Drives   : 6
Physical Drives    : 2,  3,  4,  5,  6,  7,
Name               : Virtual_Disk2
RAID Level         : 0
State              : Optimal
Number Of Drives   : 2
Physical Drives    : 8,  9,

$: mapfile -t drive < <(echo "$phyDrives3") && while read line || [[ -n "$line" ]]; do echo "$line"; [[ "$line" =~ ^Number ]] && echo "${drive[ndx++]}"; done < <(echo "$megaCliVD3")
Name               : Virtual_Disk0
RAID Level         : 1
State              : Optimal
Number Of Drives   : 2
Physical Drives    : 0,  1,
Name               : Virtual_Disk1
RAID Level         : 5
State              : Optimal
Number Of Drives   : 6
Physical Drives    : 2,  3,  4,  5,  6,  7,
Name               : Virtual_Disk2
RAID Level         : 0
State              : Optimal
Number Of Drives   : 2
Physical Drives    : 8,  9,

如果您多次使用bash循环,只需确保您(重新)初始化ndx
注意,这里可以使用here-strings而不是subshell:

$: mapfile -t drive <<< "$phyDrives3" && while read line || [[ -n "$line" ]]; do echo "$line"; [[ "$line" =~ ^Number ]] && echo "${drive[ndx++]}"; done <<< "$megaCliVD3"
suzh9iv8

suzh9iv83#

使用**ANY***awk 假设两个输入都已在虚拟驱动器级别预先排序,并且两个文件都提供完美的1对1Map *):

{m,g,n}awk '(_=FNR) == NR ? -(__[++_] = RS $!_ RS RS)\
            : _<(_*_) ? ORS = __[_]   : (_)^(RS = "")'
gdx19jrr

gdx19jrr4#

给定这些文件(特别注意没有前导空行...):

cat file1 
Name               : Virtual_Disk0  
RAID Level         : 1 
State              : Optimal  
Number Of Drives   : 2  

Name               : Virtual_Disk1  
RAID Level         : 5 
State              : Optimal  
Number Of Drives   : 6  

Name               : Virtual_Disk2  
RAID Level         : 0 
State              : Optimal  
Number Of Drives   : 2 

cat file2
Virtual Drive: 0 Physical Drives ids:  0,  1,
Virtual Drive: 1 Physical Drives ids:  2,  3,  4,  5,  6,  7,
Virtual Drive: 2 Physical Drives ids:  8,  9,

您可以在paragraph mode中使用awk,这样每个由\n\n分隔的块都是一条记录,每个由\n分隔的行都是一个字段:

awk 'BEGIN{RS=""; FS=OFS="\n"}
NR==1{split($0, line); next} # file2
{printf("%s\n%s\n\n", $0, line[FNR])}' file2 file1

图纸:

Name               : Virtual_Disk0  
RAID Level         : 1 
State              : Optimal  
Number Of Drives   : 2  
Virtual Drive: 0 Physical Drives ids:  0,  1,

Name               : Virtual_Disk1  
RAID Level         : 5 
State              : Optimal  
Number Of Drives   : 6  
Virtual Drive: 1 Physical Drives ids:  2,  3,  4,  5,  6,  7,

Name               : Virtual_Disk2  
RAID Level         : 0 
State              : Optimal  
Number Of Drives   : 2 
Virtual Drive: 2 Physical Drives ids:  8,  9,

通过您的编辑,给定这些文件:

cat file1
Name               : Virtual_Disk0  
RAID Level         : 1 
State              : Optimal  
Number Of Drives   : 2  
Name               : Virtual_Disk1  
RAID Level         : 5 
State              : Optimal  
Number Of Drives   : 6  
Name               : Virtual_Disk2  
RAID Level         : 0 
State              : Optimal  
Number Of Drives   : 2 

cat file2
Physical Drives    : 0,  1,
Physical Drives    : 2,  3,  4,  5,  6,  7,
Physical Drives    : 8,  9,

这个awk:

awk '
NR==FNR{line[FNR]=$0; next} # file2
/^Number/{printf("%s\n%s\n", $0, line[++cnt]); next}
1' file2 file1

图纸:

Name               : Virtual_Disk0  
RAID Level         : 1 
State              : Optimal  
Number Of Drives   : 2  
Physical Drives    : 0,  1,
Name               : Virtual_Disk1  
RAID Level         : 5 
State              : Optimal  
Number Of Drives   : 6  
Physical Drives    : 2,  3,  4,  5,  6,  7,
Name               : Virtual_Disk2  
RAID Level         : 0 
State              : Optimal  
Number Of Drives   : 2 
Physical Drives    : 8,  9,

相关问题