【问题标题】:AWK error - syntax error at or near grepAWK 错误 - grep 处或附近的语法错误
【发布时间】:2014-11-05 01:42:47
【问题描述】:

我需要创建一个脚本来解绑/绑定一台 linux 机器上的所有 USB。

为此我需要运行:

lsusb -t 返回:

root@lsdg7sd-fc:~# lsusb -t
/:  Bus 02.Port 1: Dev 1, Class=root_hub, Driver=ohci_hcd/10p, 12M
    |__ Port 4: Dev 2, If 0, Class=vend., Driver=ftdi_sio, 12M
    |__ Port 6: Dev 4, If 0, Class=HID, Driver=usbhid, 1.5M
    |__ Port 6: Dev 4, If 1, Class=HID, Driver=usbhid, 1.5M
/:  Bus 01.Port 1: Dev 1, Class=root_hub, Driver=ehci_hcd/10p, 480M

现在,对于这个例子,我需要运行:

 // disable the bus 1, port 1
 echo '2-4' | tee /sys/bus/usb/drivers/usb/unbind
 // disable the bus 1, port 2
 echo '2-6' | tee /sys/bus/usb/drivers/usb/unbind
 // enable the bus 1, port 1
 echo '2-4' | tee /sys/bus/usb/drivers/usb/bind
 // enable the bus 1, port 2
 echo '2-6' | tee /sys/bus/usb/drivers/usb/bind

为了通过创建脚本来实现这一点(我对 linux 很陌生),我做了以下操作:

#!/bin/bash

lsusb -t | awk '{

bus="";
if($1=="|__")
      print "Child USB Port: ",$3;
else if ($1=="/:") {
      print $3;
      var= $(echo $3 | grep -o "[1-9]");
      echo $var;
}
}'

var=`echo "02.Port" | grep -o "[1-9]"`;
echo $var;
var=`echo "02.Port" | grep -o "[0-9]\{2\}"`;
echo $var;

我尝试了所有可能的组合来设置 var.我总是出错。

awk: line 8: syntax error at or near grep

谁能提出解决方案或其他方法?

感谢阅读。

---------- 更新

感谢 Ed Morton,输入是命令 lsusb -t 的结果:(在我的结尾)

/:  Bus 02.Port 1: Dev 1, Class=root_hub, Driver=ohci_hcd/10p, 12M
    |__ Port 4: Dev 2, If 0, Class=vend., Driver=ftdi_sio, 12M
    |__ Port 6: Dev 4, If 0, Class=HID, Driver=usbhid, 1.5M
    |__ Port 6: Dev 4, If 1, Class=HID, Driver=usbhid, 1.5M
/:  Bus 01.Port 1: Dev 1, Class=root_hub, Driver=ehci_hcd/10p, 480M

我想解析这些信息以获取 BUS 号和端口号。所以输出应该是:

2-1
2-4
2-6
2-6
1-1

但是,我只需要“子”端口,所以我需要以下输出:

2-4
2-6
2-6

再次感谢!

【问题讨论】:

  • 你在这里有 awk 与 shell 脚本的混淆。几乎没有一个“awk 脚本”实际上是有效的 awk 脚本。
  • 你也不应该使用旧的和过时的反引号,使用这样的括号:var=$(echo "02.Port" | grep -o "[1-9]");
  • 感谢您的 cmets!我将开始使用 $() 而不是 back-tics

标签: linux bash awk usb lsusb


【解决方案1】:

shell 是一个调用 UNIX 工具的环境,使用一种语言来对这些调用进行排序。

grep 是一个 UNIX 工具,用于从匹配正则表达式的文件(或管道)中打印行。

awk 是用于处理文本的标准通用 UNIX 工具。

它们是 3 种完全不同的工具,具有自己的语言/语法。

您可以从 shell 调用 grep 来查找正则表达式并打印匹配的行。

您可以从 shell 调用 awk 来执行更复杂的文本操作操作,这些操作可能包括也可能不包括 grep 可以做的任何事情。

您不会从 awk 调用 grep,也不能从 grep 调用 awk。

你可以在一些非常罕见的情况下从 awk 调用 shell,但你不能从 grep 调用 shell。

您在问题中发布了一些示例输入,现在更新它以显示您希望在对该输入运行工具后获得的特定输出,以便我们可以帮助您编写工具来执行此操作。

如果它有用,这里是正确的 awk 语法,让 awk 脚本执行您尝试使用 echo 和 grep 等执行的操作:

$ cat tst.awk
{
    if (/\|__/) {
        print "Child USB Port: ",$3
    }
    else {
        print $3
        var = $3
        gsub(/[^[:digit:]]/,"",var)
        print var
    }
}
$
$ awk -f tst.awk file
02.Port
02
Child USB Port:  4:
Child USB Port:  6:
Child USB Port:  6:
01.Port
01

鉴于您更新的问题:

$ cat tst.awk
{
    var = $3+0
    if (/\/:/) {
        bus = var
    }
    else {
        print bus "-" var
    }
}
$
$ awk -f tst.awk file
2-4
2-6
2-6

请注意,如果您希望将其转到几个文件以及标准输出,那么您所需要的而不是后续的 echo+pipe+tee 就是:

BEGIN{
    path   = "/sys/bus/usb/drivers/usb/"
    unbind = path "unbind"
    bind   = path "bind"
}
{
    var = $3+0
    if (/\/:/) {
        bus = var
    }
    else {
        busPort = bus "-" var
        print busPort
        print busPort > unbind
        print busPort > bind
    }
}

而且由于重复您已经处理过的总线+端口组合的操作似乎没有意义(例如第二个 2-6):

BEGIN{
    path   = "/sys/bus/usb/drivers/usb/"
    unbind = path "unbind"
    bind   = path "bind"
}
{
    var = $3+0
    if (/\/:/) {
        bus = var
    }
    else {
        busPort = bus "-" var
        if (!seen[busPort]++) {
            print busPort
            print busPort > unbind
            print busPort > bind
        }
    }
}

【讨论】:

  • 感谢您的回复。我想要做的是执行这个命令。回声'2-4' | tee /sys/bus/usb/drivers/usb/unbind(然后再次绑定。)。我需要编写一个脚本来查找 BUS 和端口号以执行此命令。我正在考虑另一种方法,例如 ls /sys/bus/usb/drivers/usb | grep "-",这将返回我需要的内容。但是我想学习,如果你知道另一种使用 lsusb 命令来实现这一点的方法,那就太好了!
  • 我从来没有听说过 lsusb 命令,也不知道你说的“然后再次绑定”等是什么意思。我不知道你工作的域。我做什么知道如何使用 shell 命令使用 awk 和/或其他 UNIX 工具将文本从一种格式转换为另一种格式,因此如果您需要帮助,请更新您的问题以显示示例输入和预期输出。如果您只是想execute this command. echo '2-4' | tee /sys/bus/usb/drivers/usb/unbind,那么请继续执行该命令,但这似乎与您发布的输入完全无关
  • 我已经用您要求的信息更新了问题。感谢您的帮助!
  • 好的,我已经更新了我的答案以匹配,并展示了如何在没有单独的回声、三通和管道之后做我认为你最终想要的。
  • 是的,非常感谢您的帮助。不确定为什么 bind 和 unbind 命令不起作用。但这可能是另一个问题,我将继续学习。再次感谢!
【解决方案2】:

你不能在awk里面定义变量

var= $(echo $3 | grep -o "[1-9]"

做一些这样的事情:

awk -v var=$(echo $3 | grep -o "[1-9]" '{print var}' file

PS 我不明白你为什么需要同时使用 awkgrep

【讨论】:

  • 我认为他的脚本中的$3 旨在成为他输入每一行的第三个字段,而不是传递给他的 shell 脚本的第三个参数。没错,如果你已经在使用 awk,你就不会使用 grep。
猜你喜欢
  • 2017-02-20
  • 2017-07-15
  • 2010-12-24
  • 2016-07-10
  • 2018-11-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多