Ошибка AWK - синтаксическая ошибка в grep или рядом с ним

Мне нужно создать скрипт для отключения/привязки всех usb на одной Linux-машине.

Для этого мне нужно запустить:

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

Может ли кто-нибудь предложить решение или другой подход?

Спасибо за чтение.

---------------------- Обновлять

Спасибо, Эд Мортон, ввод является результатом команды 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

Спасибо еще раз!


person Juano7894    schedule 04.11.2014    source источник
comment
У вас здесь путаница сценариев awk и shell. Практически ни один из этих awk-скриптов не является действительным awk-скриптом.   -  person Etan Reisner    schedule 04.11.2014
comment
Также не следует использовать старые и устаревшие обратные тики, используйте такие скобки: var=$(echo "02.Port" | grep -o "[1-9]");   -  person Jotne    schedule 04.11.2014
comment
Спасибо за ваши комментарии!. Я начну использовать $() вместо обратных тиков   -  person Juano7894    schedule 04.11.2014


Ответы (2)


оболочка — это среда, из которой можно вызывать инструменты UNIX, с языком для последовательности этих вызовов.

grep — это инструмент UNIX для печати строк из файлов (или конвейеров), соответствующих регулярным выражениям.

awk — это стандартный универсальный инструмент UNIX для обработки текста.

Это 3 совершенно разных инструмента со своими языками/синтаксисом.

Вы должны вызвать grep из оболочки, чтобы найти регулярное выражение и напечатать соответствующую строку.

Вы бы вызывали awk из оболочки для выполнения более сложных операций по манипулированию текстом, которые могут включать или не включать что-либо, что может сделать grep.

Вы НЕ будете вызывать grep из awk, и вы НЕ МОЖЕТЕ вызывать awk из grep.

Вы можете вызывать оболочку из awk в некоторых очень редких ситуациях, когда это полезно, но вы не можете вызывать оболочку из grep.

Вы опубликовали пример ввода в своем вопросе, теперь обновите его, чтобы показать конкретный вывод, который вы хотели бы получить в результате запуска инструмента на этом вводе, чтобы мы могли помочь вам написать инструмент для этого.

Если это полезно, вот правильный синтаксис awk для скрипта awk, чтобы делать то, что вы пытаетесь сделать с эхом, 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

Обратите внимание: если вы хотите, чтобы это перешло к паре файлов, а также к стандартному выводу, тогда все, что вам нужно вместо последующего эха + канала + тройника, это:

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
        }
    }
}
person Ed Morton    schedule 04.11.2014
comment
Спасибо за ответ. Я пытаюсь выполнить эту команду. эхо '2-4' | tee /sys/bus/usb/drivers/usb/unbind (затем снова свяжите). Что мне нужно, так это написать сценарий, чтобы найти BUS и номер порта, чтобы выполнить эту команду. Я думаю о другом подходе, например, ls /sys/bus/usb/drivers/usb | grep - это вернет то, что мне нужно. Но я хочу узнать, если вы знаете другой способ использовать команду lsusb для достижения этой цели, будет здорово! - person Juano7894; 04.11.2014
comment
Я никогда не слышал о команде lsusb и поэтому не знаю, что вы имеете в виду, когда говорите о повторной привязке и т. д. Я не знаю домена, в котором вы работаете. Что я знаю, так это как использовать команды оболочки для преобразования текста. из одного формата в другой с помощью awk и / или других инструментов UNIX, поэтому, если вам нужна помощь в этом, обновите свой вопрос, чтобы показать образец ввода и ожидаемый результат в соответствии с запросом. Если вы просто хотите execute this command. echo '2-4' | tee /sys/bus/usb/drivers/usb/unbind, тогда просто выполните эту команду, но это кажется совершенно не связанным с опубликованным вами вводом. - person Ed Morton; 04.11.2014
comment
Я обновил вопрос с информацией, которую вы запросили. Спасибо за помощь! - person Juano7894; 04.11.2014
comment
Хорошо, я обновил свой ответ, чтобы он соответствовал, и показал, как делать то, что, Я ДУМАЮ, вы в конечном итоге хотите, без отдельного эха, тройника и трубы впоследствии. - person Ed Morton; 04.11.2014
comment
Да, большое спасибо за помощь. Не уверен, почему команды привязки и отвязки не работают. Но это может быть другая проблема, я буду продолжать изучать это. ЕЩЕ РАЗ СПАСИБО! - person Juano7894; 04.11.2014

Вы не можете определить переменную внутри awk

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

Сделайте вот так:

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

PS Не понимаю, почему нужно использовать и awk, и grep

person Jotne    schedule 04.11.2014
comment
Я думаю, что $3 в его сценарии предназначено быть третьим полем в каждой строке его ввода, а не третьим аргументом, передаваемым в его сценарий оболочки. И правильно, вы бы не использовали grep, если уже используете awk. - person Ed Morton; 04.11.2014