изменить поток данных на лету - PullRequest
0 голосов
/ 22 августа 2010

Мне нужно перехватить и изменить поток данных.Поток состоит из команд фиксированной ширины.Каждая команда представляет собой новую строку, и в документации говорится, что каждая команда начинается и заканчивается парой STX / ETX (начало и конец текста)

Отправляющая система использует последовательный порт, но подвергается атакена устройство iPocket, которое связывается по IP с нашей УАТС.Из того, что я могу сказать, это просто преобразование серийного номера в telnet, что, как мы надеемся, должно сделать все довольно просто.

Строка, которую мне нужно искать, начинается с NAM.Структура выглядит примерно так:

STX NAM EXT# LASTNAME,FIRSTNAME ETX

Мне нужно заменить ,FIRSTNAME пробелом, чтобы он не менял длину команды.

IМы пытались выполнить следующее, и хотя он пропускает данные из конца в конец в обоих направлениях, как требуется, и удаляет необходимые данные, он не поддерживает длину команды.

ipocket <-> nc -kl 1100 | sed 's/,[^,]*/ /g' | nc target_ip target_port <-> PBX

Я буду использовать linux box для этой задачи.Я достаточно уверен, что это можно сделать довольно просто на Perl или Python, но я не знаю, с чего начать.Будем очень благодарны любой помощи!

Ответы [ 5 ]

2 голосов
/ 22 августа 2010

Это должно сделать, это один лайнер

perl -pe '/^STX\s\w+\s\d+#\s\w+,(\w+)\sETX$/;$len=length($1);s/$1/" " x $len/e'

Я тестировал, используя.

echo "STX NAM 100# LASTNAME,FIRSTNAME ETX" | perl -pe '/^STX\s\w+\s\d+#\s\w+,(\w+)\sETX$/;$len=length($1);s/$1/" " x $len/e'

и возвращается

STX NAM 100# LASTNAME,          ETX

Чтобы обеспечить одинаковую длину строк, которые я тестировал.

echo "STX NAM 100# LASTNAME,FIRSTNAME ETX" | perl -pe '/^STX\s\w+\s\d+#\s\w+,(\w+)\sETX$/;$len=length($1);s/$1/" " x $len/e'| perl -pe 'print length($_);'

Дает 36.

echo "STX NAM 100# LASTNAME,FIRSTNAME ETX"|perl -pe 'print length($_);'

Дает 36.

0 голосов
/ 04 октября 2012

Да, iPocket выполняет сквозную передачу данных.Варианты, как правило, предназначены для пакетирования входящих данных, которые фактически не влияют на то, что вы пытаетесь сделать здесь.(Я написал прошивку для этого устройства.)

Однако ни один из ответов командной строки здесь не будет работать, потому что они основаны на строках, а ваши данные - нет.То есть в потоке данных есть строки, которые sed и perl используют в качестве границ "пакета".

Я не верю, что вы сможетечтобы сделать это из командной строки.Вам нужно написать простую программу, которая читает входящий поток TCP, ищет кадры STX / ETX, заменяет символы по вашему желанию, а затем записывает данные на другую сторону.(Не забывайте также проходить в обратном направлении.)

Возможно, Python - самый простой способ сделать это.

0 голосов
/ 23 августа 2010

Вот версия sed:

sed 'h;s/[^,]*,\([^ ]*\) ETX/\1/;s/./ /g;x;s/,.*/,/;G;s/\n//;s/$/ ETX/'

Я бы хотел поспорить, что команда не только имеет фиксированную ширину, но и поля также имеют фиксированную ширину.Если это так, то что-то вроде этого, вероятно, будет работать:

sed 's/\(.\{22\}\).\{9\}\(.\{4\}\)/\1         \2/'

или

sed -r 's/(.{22}).{9}(.{4})/\1         \2/'

или

sed -r 's/STX (.{18}).{9} ETX/STX \1          ETX/'
0 голосов
/ 22 августа 2010

Вместо команды sed вы можете использовать это:

perl -pe 's/(,\w+)/" " x length $1/ge'

Параметр e в замещении означает, что правая часть s/// оценивается как выражение Perl.В этом случае выражение возвращает правильное количество пробелов в зависимости от длины захваченного совпадения.

0 голосов
/ 22 августа 2010

В Perl с добавлением проверьте, что строка начинается с с NAM и действительно заменяет ,FIRSTNAME:

nc -kl 1100 | \
perl -pe '/^STX NAM / && do { s/(,FIRSTNAME)/" " x length("$1")/ge }' | \
nc <...>

В Perl s///e, как и ожидалось, выполняет подстановку, но оценивает замещающую строку как выражение e xpression. Оператор x создает новую строку, дублируя строку слева, количество раз приведенное справа. Несоответствующие строки явно не модифицируются.

...