特定文本的bash过滤器/条带输出

时间:2014-03-11 11:03:14

标签: bash sed awk

给出dmesg日志输出,特别是其中的一行,例如:

NET: Registered protocol family 10

在脚本中我希望有一个定义的变量,如$net_version,它将检查我是否定义了值为10,如果它与在dmesg中找到的那个匹配。

我同时看了sed和awk,但是对于awk我找不到正确的方法来剥离输出,只是将变量与dmesg行中的最后一个字匹配。

我认为这是一个简单的问题,但是我在确定正确的方法时遇到了问题。

3 个答案:

答案 0 :(得分:3)

您可以使用sed打印匹配的行:

var=10
sed -n "/NET: Registered protocol family $var/p" file
  • -n避免打印所有行。
  • "/NET: .... $var/p"用户使用doubleq引号扩展变量。
  • /p打印匹配的行。

当然还是grep

$ grep "NET: Registered protocol family $var" file

实施例

$ cat a
NET: Registered protocol family 10
NET: Registered protocol family 7
NET: Registered protocol family hello
bye

$ var=10
$ sed -n "/NET: Registered protocol family $var/p" a
NET: Registered protocol family 10

$ var=7
$ sed -n "/NET: Registered protocol family $var/p" a
NET: Registered protocol family 7

$ var=5
$ sed -n "/NET: Registered protocol family $var/p" a
$

使用grep

$ var=10
$ grep "NET: Registered protocol family $var" a
NET: Registered protocol family 10

答案 1 :(得分:3)

我建议不要使用无锚的正则表达式。如果“NET:Registered protocol family 100”不应该匹配,那么这里的其他一些答案可能会给你误报。

在以下grep解决方案中,请注意正则表达式末尾的锚点。此外,grep的-q选项使其“安静”,以便它可以简单地用于通知您的if

#!/bin/sh

val="10"

if dmesg | grep -q "^NET: Registered protocol family ${val}$"; then
  echo "matched"
fi

或者,您可以使用awk,但是您需要两个条件 - 一个匹配行上的字符串,另一个匹配变量。

awk -v val="10" '/^NET: Registered protocol family / && $NF==val { print "matched" }'

或者您可以使用单个字符串匹配来执行此操作:

awk -v val="10" '$0 == "NET: Registered protocol family "val { print "matched" }'

或者如果您想在shell脚本中使用sed strip 输出进行评估,可以这样做:

#!/bin/bash

val=$(dmesg | sed -ne '/^NET: Registered protocol family /{;s///p;q}')

if [ "$val" -eq "10" ]; then
  echo "matched"
fi

这里的sed脚本看起来有点复杂,所以让我们把它分解出来......

  • -n选项告诉它默认不打印输出,
  • 我们首先搜索包含NET:文本的行,如果找到,
    • 我们用“找不到”的文字替换(因此剥离它),
    • 命令末尾的p告诉它在替换成功时打印输出,并且
    • 我们退出,从而保护自己免受多次出现的字符串。

如果您希望能够在dmesg文件中处理多次出现,则可能需要通过循环运行:

#!/bin/sh

dmesg \
 | sed -ne '/^NET: Registered protocol family /{;s///p;q}') \
 | while read val; do

     if [ "$val" -eq "10" ]; then
       echo "matched"
     fi

   done

我已将dmesg管道拆分为多行,以便于在此处阅读,但您可以在脚本中将其全部放到一行。

答案 2 :(得分:0)

需要做类似的事情,但要找到USB闪存驱动器信息。我从命令开始:

    dmesg | grep -i 'scsi' | grep -i removable

我得到2个结果:

    [    3.197914] sd 2:0:0:0: [sdc] Attached SCSI removable disk
    [22373.515566] sd 3:0:0:0: [sdd] Attached SCSI removable disk

然后我需要循环获取sdc和sdd值并插入var $ SDDRV以运行下一个cmd:

    fdisk -l | grep -i disk | grep ${SDDRV}

如果磁盘实际上没有附加(这种情况是sdc),fdisk cmd什么都不产生,但是因为在这种情况下sdd是活动的,结果是:

    Disk /dev/sdd: 63.2 GB, 63216549888 bytes

然后我需要解析闪存驱动器的大小,即63.2 GB(我的64GB闪存),并且因为大小超过63GB,所以将SDNAM设置为“64Gig”(闪存名称)。我有1GB,2GB,16GB和64GB,所以必须有逻辑来为任何/所有插入的驱动器获取正确的名称,并且你看到linux看到的大小不等于mfg size标签。不知道为什么,但仍然需要为每个插入的设备获得正确的名称。

接下来我需要运行命令:

    df -h | grep ${SDDRV}

结果,我正在显示'df'中的列标签:

    Filesystem      Size  Used Avail Use% Mounted on
    /dev/sdd1        59G   11M   59G   1% /media/ndavis/USB DISK

由此我必须解析'可用空间'和'挂载点'

如果我处理所有这些,那么我应该:

  1. 驱动器名称,
  2. 驱动器尺寸,
  3. 可用空间,
  4. 挂载点
  5. 然后我创建一个包含所有这些的单个VAR并将其导出,以便其他需要USB闪存驱动器信息的脚本可以使用它。