如何将一个变量的 2 行添加到另一个变量的特定行?

问题描述 投票:0回答:6

我有这些输出的变量:

$nw_monitor
Host has 'em3, em2, em1, em4' network devices
em3 does not have any ip rules, skipping health checks
Checking health of 'em2'
Checking health of 'em1'
em4 does not have any ip rules, skipping health checks
Host has 2 healthy network links

和第二个变量。

$link
Speed              : 10 Gb/s
Link status        : yes
Speed              : 10 Gb/s
Link status        : yes

从第二个变量开始,它给出了 $nw_monitor、em2 和 em1 中提到的每个接口的速度和链接状态。

所以我想把它们混合起来,看起来像这样:

Host has 'em3, em2, em1, em4' network devices
em3 does not have any ip rules, skipping health checks
Checking health of 'em2'
Speed              : 10 Gb/s
Link status        : yes
Checking health of 'em1'
Speed              : 10 Gb/s
Link status        : yes
em4 does not have any ip rules, skipping health checks
Host has 2 healthy network links

我试过这个:

sed /^Checking/R<(echo "$link") <(echo "$nw_monitor")

但是,我得到他的输出:

Host has 'em3, em2, em1, em4' network devices
em3 does not have any ip rules, skipping health checks
Checking health of 'em2'
Speed              : 10 Gb/s
Checking health of 'em1'
Link detected      : yes
em4 does not have any ip rules, skipping health checks
Host has 2 healthy network links
linux bash awk sed centos7
6个回答
5
投票

为什么它们是字符串?我认为这在简单文件中会更容易。

$: echo "$nw_monitor">a
$: echo "$link">b
$: while read a
>  do echo "$a"
>     case "$a" in Checking*) for c in 1 2; do read b <&3; echo " $b"; done;; esac
>  done <a 3<b
Host has 'em3, em2, em1, em4' network devices
em3 does not have any ip rules, skipping health checks
Checking health of 'em2'
 Speed              : 10 Gb/s
 Link status        : yes
Checking health of 'em1'
 Speed              : 10 Gb/s
 Link status        : yes
em4 does not have any ip rules, skipping health checks
Host has 2 healthy network links

但是如果你只需要它们在字符串中......

$: while read a
>  do echo "$a"
>     case "$a" in Checking*) for c in 1 2; do read b <&3; echo " $b"; done;; esac
>  done < <(echo "$nw_monitor") 3< <(echo "$link")
Host has 'em3, em2, em1, em4' network devices
em3 does not have any ip rules, skipping health checks
Checking health of 'em2'
 Speed              : 10 Gb/s
 Link status        : yes
Checking health of 'em1'
 Speed              : 10 Gb/s
 Link status        : yes
em4 does not have any ip rules, skipping health checks
Host has 2 healthy network links

2
投票

awk
,也许:

awk 'NR==FNR {link[i++] = $0; next} {print}
  /^Checking health of / {print link[j++]; print link[j++]}
' <( printf '%s\n' "$link" ) <( printf '%s\n' "$nw_monitor" )

awk
脚本将变量
link
的行存储在索引(从 0 开始)数组中,也称为
link
。当解析第二个变量时,它只是在以
link
.
开头的任何行之后添加两行数组
Checking health of

2 个 bash 进程替换

<( printf ... )
是一种将变量转换为看起来像文件的方法
awk
.


2
投票

假设:

  • re:
    $link
    - 链接的第一行数据总是包含字符串
    Speed
  • re:
    $link
    - OP 的示例显示每个链接都有 2 行数据,但我们假设这可能会有所不同
  • re:
    $nw_monitor
    - 感兴趣的行总是包含字符串
    Checking health
  • re:
    $nw_monitor
    - OP 的示例显示了 2 组链接数据和 2
    Checking health
    行,但我们假设我们可以有额外的
    Checking health
    行没有匹配的链接数据

设置:

nw_monitor="Host has 'em3, em2, em1, em4' network devices
em3 does not have any ip rules, skipping health checks
Checking health of 'em2'
Checking health of 'em1'
Checking health of 'emXXX'                                    # new; no match in $link
em4 does not have any ip rules, skipping health checks
Host has 2 healthy network links"

link="Speed              : 10 Gb/s
Link status        : yes
Link desc          : random stuff comment string              # new; this link data set consists of 3 lines
Speed              : 10 Gb/s
Link status        : yes"

注意:实际数据中不存在注释

一个

awk
想法:

awk -v mon="$nw_monitor" -v link="$link" '              # pass bash variables to awk
BEGIN { n=split(link,a,RS)                              # split link on default RS="\n" delimiter, put data in a[] array

        for (i=1;i<=n;i++) {                            # loop through indices of the a[] array
            if (a[i] ~ /Speed/) { linkid++; sep="" }    # if this is a new set of link data then increment our linkid and clear the separator
            links[linkid] = links[linkid] sep a[i]      # append to links[] array
            sep=ORS                                     # set separator to default ORS="\n" for 2nd-nth lines of this link data set
        }

        linkid=0
        n=split(mon,a,RS)                               # split nw_monitor on default RS="\n" delimiter, put data in a[] array (array will be cleared of previous link-related data)

        for (i=1;i<=n;i++) {                            # loop through indices of the a[] array
            print a[i]                                  # print current line
            if (a[i] ~ /Checking health/) {             # if this is a line of interest then ...
               if (++linkid in links)                   # increment linkid and if a valid index of the links[] array then ...
                  print links[linkid]                   # print contents of the associated links[] array
               else
                  print "    WARNING: no link data"
            }
        }
      }
'

这会产生:

Host has 'em3, em2, em1, em4' network devices
em3 does not have any ip rules, skipping health checks
Checking health of 'em2'
Speed              : 10 Gb/s
Link status        : yes
Link desc          : random stuff comment string
Checking health of 'em1'
Speed              : 10 Gb/s
Link status        : yes
Checking health of 'emXXX'
    WARNING: no link data
em4 does not have any ip rules, skipping health checks
Host has 2 healthy network links

1
投票

使用您展示的示例和尝试,请尝试遵循

awk
代码。这使用变量
link
作为第一个输入和变量
nw_monitor
作为
awk
程序的第二个输入并打印所需的输出。

awk '
FNR==NR{
  if($0~/^Speed/){
    value[++i]=$0
    next
  }
  if($0~/^Link status/){
    value[i]=(value[i]?value[i] ORS:"") $0
  }
  next
}
/^Checking/{
  print $0 ORS value[++j]
  next
}
1
'  <( printf '%s\n' "$link" ) <( printf '%s\n' "$nw_monitor" )

0
投票

这可能对你有用(GNU sed 和 bash):

cat <(echo "$link") |
sed -e '/Checking/{R /dev/stdin' -e 'R /dev/stdin' -e '}' <(echo "$nw_monitor")

传递变量

$link
作为标准输入,并为每次出现的字符串
R
.
 应用 
Checking

命令的两个实例

注意

R
命令必须由换行符终止,选项
-e
提供此功能。


替代方案:

cat <(echo "$b") | sed -e '/Checking/R /dev/stdin' -e '//R /dev/stdin' <(echo "$a")

0
投票

另一种方法。

nw_monitor

nw_monitor="Host has 'em3, em2, em1, em4' network devices
em3 does not have any ip rules, skipping health checks
Checking health of 'em2'
Checking health of 'em1'
em4 does not have any ip rules, skipping health checks
Host has 2 healthy network links"

link
第一个Speed20,状态是no,第二个Speed是10,状态是yes

link='Speed              : 20 Gb/s
Link status        : no
Speed              : 10 Gb/s
Link status        : yes'

一个外壳方法:

#!/usr/bin/env bash

head="${link%Speed*}"
tail="${link#"$head"}"
head="${head%$'\n'}"

while IFS= read -r line; do
  case "$line" in
    Checking*'em2'*)
      printf '%s\n%s\n' "$line" "$head";;
    Checking*'em1'*)
      printf '%s\n%s\n' "$line" "$tail";;
    *) printf '%s\n' "$line"
  esac
done <<< "$nw_monitor"

如果是文件,使用

ed
:


printf '%s\n' "$nw_monitor" "$link" > file.txt

ed -s file.txt <<-'EOF'
  /Speed/;/Link status/m/Checking.*'em2'/
  /Speed/;/Link status/m/Checking.*'em1'/
  ,p
  Q
EOF

  • em1
    em2
    都可以在 shell 方法的
    case
    语句内和
    / /
    方法的
    ed
    内出现。

有了上面的解决方案

em2
在前,输出:

Host has 'em3, em2, em1, em4' network devices
em3 does not have any ip rules, skipping health checks
Checking health of 'em2'
Speed              : 20 Gb/s
Link status        : no
Checking health of 'em1'
Speed              : 10 Gb/s
Link status        : yes
em4 does not have any ip rules, skipping health checks
Host has 2 healthy network links

改变

em1
em2
之前的顺序,输出:

Host has 'em3, em2, em1, em4' network devices
em3 does not have any ip rules, skipping health checks
Checking health of 'em2'
Speed              : 10 Gb/s
Link status        : yes
Checking health of 'em1'
Speed              : 20 Gb/s
Link status        : no
em4 does not have any ip rules, skipping health checks
Host has 2 healthy network links
© www.soinside.com 2019 - 2024. All rights reserved.