Фильтрация текста по awk или bash с некоторыми конкретными условиями
У меня есть выход (из хорошо известного btmon
инструмент), как в примере ниже, и мне нужно проанализировать его и получить некоторую информацию из него следующим образом: если UUID представлен в разделе HCI event:
и это равняется 32f9169f-4feb-4883-ade6-1f0127018db3
затем принять значение Address:
а также RSSI:
поля и собрать их вместе и сделать новую линию. Также каждый экземпляр должен быть помещен в определенный файл в соответствии с номером [hci] (та же строка, что и для события HCI). Например, из каждого события HCI hci 0 (отвечающего описанным условиям) он переходит в файл hci0.txt из hci1. в файл-hci1.txt и так далее для всех hciX в таком формате, как для hci0 (.txt):
A0: E6: F8: 48: 38: 6F AB
A0: E6: F8: 48: 87: DA B6
для hci1 (.txt):
A0: E6: F8: 48: 32: 94 C3
A0: E6: F8: 48: EF: 78 BA
Итак, вот поток или файл, который мне нужно проанализировать описанным способом:
> HCI Event: LE Meta Event (0x3e) plen 43 [hci1] 4.746057
LE Advertising Report (0x02)
Num reports: 1
Event type: Non connectable undirected - ADV_NONCONN_IND (0x03)
Address type: Public (0x00)
Address: A0:E6:F8:48:32:94 (Texas Instruments Inc)
Data length: 31
Flags: 0x05
LE Limited Discoverable Mode
BR/EDR Not Supported
Company: not assigned (37984)
Data: 3248f8e6a000
128-bit Service UUIDs (complete): 1 entry
32f9169f-4feb-4883-ade6-1f0127018db3
RSSI: -61 dBm (0xc3)
> HCI Event: LE Meta Event (0x3e) plen 43 [hci0] 5.198878
LE Advertising Report (0x02)
Num reports: 1
Event type: Non connectable undirected - ADV_NONCONN_IND (0x03)
Address type: Public (0x00)
Address: A0:E6:F8:48:38:6F (Texas Instruments Inc)
Data length: 31
Flags: 0x05
LE Limited Discoverable Mode
BR/EDR Not Supported
Company: not assigned (28512)
Data: 3848f8e6a000
128-bit Service UUIDs (complete): 1 entry
32f9169f-4feb-4883-ade6-1f0127018db3
RSSI: -85 dBm (0xab)
> HCI Event: LE Meta Event (0x3e) plen 43 [hci1] 5.819728
LE Advertising Report (0x02)
Num reports: 1
Event type: Non connectable undirected - ADV_NONCONN_IND (0x03)
Address type: Public (0x00)
Address: A0:E6:F8:48:EF:78 (Texas Instruments Inc)
Data length: 31
Flags: 0x05
LE Limited Discoverable Mode
BR/EDR Not Supported
Company: not assigned (30816)
Data: ef48f8e6a000
128-bit Service UUIDs (complete): 1 entry
32f9169f-4feb-4883-ade6-1f0127018db3
RSSI: -70 dBm (0xba)
> HCI Event: LE Meta Event (0x3e) plen 43 [hci0] 6.011983
LE Advertising Report (0x02)
Num reports: 1
Event type: Non connectable undirected - ADV_NONCONN_IND (0x03)
Address type: Public (0x00)
Address: A0:E6:F8:48:87:DA (Texas Instruments Inc)
Data length: 31
Flags: 0x05
LE Limited Discoverable Mode
BR/EDR Not Supported
Company: not assigned (55904)
Data: 8748f8e6a000
128-bit Service UUIDs (complete): 1 entry
32f9169f-4feb-4883-ade6-1f0127018db3
RSSI: -74 dBm (0xb6)
3 ответа
В Ruby, awk, Python, Perl вы можете:
- Разделить текст на блоки;
- Проверьте каждый блок для трех тестов регулярных выражений, которые вы описываете;
- Разобрать блок;
- Распечатать в соответствующий файл.
Первая часть помогает с помощью sed
добавить \n
между блоками, а затем использовать awk
обрабатывать каждый блок. Вот sed
а также awk
производят блоки (2 из них), которые представляют интерес:
$ sed 's / ^> / \ & / 'файл | awk -v RS="" -v FS="\n" ' /UUIDs/ && /32f9169f-4feb-4883-ade6-1f0127018db3/ && /\[hci[01]\]/'
Теперь добавьте awk
к тому к этому блоки в два файла:
$ sed 's/^>/\
&/' file |
awk -v RS="" -v FS="\n" '
/UUIDs/ && /32f9169f-4feb-4883-ade6-1f0127018db3/ && /\[hci[0-9]+\]/ {
s1=s2=fo=""
for (i=1;i<=NF;i++) {
if (match($i,/\[hci[0-9]+/))
fn=substr($i,RSTART+1,RLENGTH-1)
if (match($i,/Address: /))
s1=substr($i,RSTART+RLENGTH, 17)
else if (match($i,/ RSSI:/)) {
match($i,/\(0x[^)]+\)/)
s2=toupper(substr($i,RSTART+3, RLENGTH-4))
}
}
fo="file-" fn ".txt"
print s1 " " s2 " => " fo
print s1 " " s2 > fo
}'
$ cat file-hci0.txt
A0:E6:F8:48:38:6F AB
A0:E6:F8:48:87:DA B6
$ cat file-hci1.txt
A0:E6:F8:48:32:94 C3
A0:E6:F8:48:EF:78 BA
Файл _сценарий:
$1 == ">" {
cnt++
for (i=1;i<=NF;i++) {
if ( $i ~ /\[.*\]/ ) {
hci[cnt]=substr($i,2,length($i)-2)
}
}
}
$1 == "Address:" {
add[cnt]=$2
}
$0 ~ /32f9169f-4feb-4883-ade6-1f0127018db3/ {
fnd[cnt]=""
}
$1 == "RSSI:" {
str=substr($4,length($4)-2)
gsub("\)","",str)
rssi[cnt]=toupper(str)
}
END {
for (i in fnd) {
print add[i]" "rssi[i] > "file-"hci[i]".txt"
}
}
awk -f scriptfile filename
При использовании awk и использовании файла сценария для кода awk, когда мы встречаем ">", это означает новый блок данных, и поэтому мы увеличиваем переменную cnt. Затем мы перебираем каждое поле в этой строке и сравниваем его с чем угодно, начиная с [и заканчивая]. Этот текст затем удаляет [and] с помощью substr и добавляется в массив hci, проиндексированный с помощью cnt. Затем мы сохраняем все адреса в массиве add и текст RSSI (отформатированный с помощью substr и gsub) в rssi. Если MAC-адрес совпадает, создается массив fnd. Все массивы индексируются cnt. Наконец, мы перебираем fnd и извлекаем другие данные из других массивов, распечатывая требуемый вывод и перенаправляя для создания необходимых файлов.
Попробуйте и дайте мне знать, если это поможет вам.
awk '/> HCI Event/ && a && b{print val1,toupper(substr(val2,4,2));a=b=""} /> HCI Event/{a=1;} /UUID/ && a{getline;sub(/^[[:space:]]+/,"");if($0 == "32f9169f-4feb-4883-ade6-1f0127018db3"){b=1}} /Address/ && a{val1=$2;} /RSSI/ && a{val2=$4;}' Input_file
Слишком скоро добавит не одну линейную форму решения.
РЕДАКТИРОВАТЬ: Добавление не один вкладыш формы решения тоже сейчас.
awk '/> HCI Event/ && a && b{
print val1,toupper(substr(val2,4,2));a=b=""}
/> HCI Event/{a=1;}
/UUID/ && a {
getline;
sub(/^[[:space:]]+/,"");
if($0 == "32f9169f-4feb-4883-ade6-1f0127018db3"){b=1}
}
/Address/ && a{val1=$2;}
/RSSI/ && a{val2=$4;}
' Input_file