У меня есть Kali в качестве виртуальной машины VirtualBox, и я установил драйвер AWUS036ACH с
apt install realtek-rtl88xxau-dkms
После этого выполните следующие команды, чтобы активировать режим монитора:
ifconfig wlan0 down
iwconfig wlan0 mode monitor
ifconfig wlan0 up
Для полноты картины решение на основе awk
-.
Скриптawk
-(назовем егоconvert_csv.awk
):
#!/bin/awk -f
BEGIN{FS=":";OFS=","}
# Process all non-empty lines
NF>0{
# Check if the "key" part of the line was not yet encountered, both globally
# and for the currently processes record.
# If not encountered globally yet, add to list of headers (=columns).
new_hdr=1; new_key=1;
for (i=1; i<=n_hdrs; i++) {if (hdr[i]==$1) new_hdr=0;}
if (new_hdr) hdr[++n_hdrs]=$1;
for (key in val) {if (key==$1) new_key=0;}
# Once no globally new keys are found, consider the "list of headers" as
# complete and print it as CSV header line.
if (!new_hdr && !hdr_printed)
{
for (i=1;i<=n_hdrs;i++) printf("%s%s", hdr[i], i==n_hdrs?ORS:OFS);
hdr_printed=1;
}
# If the current key was already found in the currently processed record,
# we assume that a new record was started, and print the data collected
# so far before collecting data on the next record.
if (!new_key)
{
for (i=1;i<=n_hdrs;i++) printf("%s%s", val[hdr[i]], i==n_hdrs?ORS:OFS);
delete val;
}
# Associate the "value" part of the line with the "key", perform transformations
# as necessary. Since both the 'gsub()' function used for escaping '"' to '""'
# and the 'index()' function used to localize ',' return non-zero if an occurence
# was found, the sum of both return values being > 0 indicates that the field
# must be quoted.
quote=gsub("\"","\"\"",$2)+index($2,",");
if (quote) $2="\""$2"\"";
val[$1]=$2;
}
# Print the last record. If it was the only record, print the header line, too (this
# is the case if 'new_hdr' is still 'true' at end-of-file).
END {
if (new_hdr)
{
for (i=1;i<=n_hdrs;i++) printf("%s%s", hdr[i], i==n_hdrs?ORS:OFS);
}
for (i=1;i<=n_hdrs;i++) printf("%s%s", val[hdr[i]], i==n_hdrs?ORS:OFS);
}
Функция описана в комментариях, но в основном она ищет наборы уникальных ключей и считает запись завершенной, как только ключ, «уже встречавшийся» в строке, найден; затем он печатает запись и очищает временный буфер для сбора следующей записи. Он также применяет преобразования, указанные @mosvy, чтобы соответствовать стандарту CSV для специальных символов в полях.
Назовите это как
awk -f convert_csv.awk input.txt
Использование perl
, которое присутствует в любом настольном или серверном дистрибутиве Linux:
perl -lne '
BEGIN{$,=","}
($k,$v)=split":",$_,2;
next unless defined $v;
for($k,$v){s/"/""/g,$_=qq{"$_"}if/[$,"]/}
$k=$t{$k}//=$t++;
if(exists$f[$k]){print@f;@f=()}
$f[$k]=$v;
END{print@f;print STDERR sort{$t{$a}<=>$t{$b}}keys%t}
' your_file
Это должно преобразовать файл в стандартный CSV, за исключением того, что заголовок (первая строка с именами полей )будет напечатана в stderr после обработки всего файла. Вы можете сохранить его где-нибудь с помощью ... >body 2>hdr
, а затем cat hdr body > final_file.csv
.
Это не придает особого значения пустым строкам и т. д. :запись считается состоящей из группы полей, которые имеют разные имена, независимо от того, в каком порядке они расположены.
Поля, которые содержат либо ,
, либо "
, будут помещены внутрь "..."
, а любое внутреннее "
будет экранировано путем дублирования его как""
(с использованием соглашения CSV ).
Вы можете настроить разделитель полей, изменив $,=","
, например, на.$,="|"
(или $,="\t"
для вкладок ). Вы можете избавиться от кавычек и экранирования, удалив строку for($k,$v){... }
.
Это можно было бы сделать вawk
(НЕ в sed
или tr
, хотя ), только это будет немного сложнее, так как awk
не имеет возможности печатать целые массивы сразу (вы должны перебирать их в цикле ), а возможность разбить строку на ограниченное число полей (вам придется использовать substr
трюк для этого ).