1 (изменено: DnsIs, 2013-10-01 12:20:52)

Тема: sed, регулярные выражения

Доброго времени суток.

Появилась потребность из строки, вытащить с помощью регулярки слово ACTIVE (может стоять другое), sed в помощь

echo "D/RILJ    ( 1379): [3554]< GET_CURRENT_CALLS  [id=1,ACTIVE,toa=145,norm,mt,0,voc,noevp,,cli=1,,0]" | sed 'REG'

Требуется подобрать REG.

У меня есть вариант, пока не буду выкладывать, хотелось бы красивого решения, а у меня страшное и длинное.

Напомню, sed - жадина.

Благодарю.

Нас невозможно сбить с пути, нам пофигу куда идти.

2

Re: sed, регулярные выражения

Не понятно, что же дальше. Нашли строку, а потом? Напечатать только эту строку, напечатать только найденное слово, изменить содержимое данной строки?

Если понимать буквально

вытащить с помощью регулярки слово

, то для этого лучше использовать grep

grep -o ACTIVE FILENAME

Если же все-таки хочется использовать sed, то может быть так:

sed -n '/.*\(ACTIVE\).*/\1/' FILENAME
sed -r -n '/.*(ACTIVE).*/\1/' FILENAME

Понятно, что вместо ACTIVE может быть какое-то выражение, поэтому имеет смысл уточнять, например

sed -n '/.*\(ACTIVE,[^,]*\).*/\1/' FILENAME
sed -r -n '/.*(ACTIVE,[^,]*).*/\1/' FILENAME
( 2 * b ) || ! ( 2 * b )

3

Re: sed, регулярные выражения

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

Суть такова, имеем лог

...
D/RILJ    ( 1379): [3157]> GET_CURRENT_CALLS
D/RILJ    ( 1379): [UNSL]< UNSOL_RESPONSE_CALL_STATE_CHANGED
D/RILJ    ( 1379): [3158]> GET_CURRENT_CALLS
V/RILJ    ( 1379): Incoming UUS : NOT present!
D/RILJ    ( 1379): InCall VoicePrivacy is disabled
D/RILJ    ( 1379): [3157]< GET_CURRENT_CALLS  [id=1,DIALING,toa=145,norm,mo,0,voc,noevp,,cli=1,,0] 
V/RILJ    ( 1379): Incoming UUS : NOT present!
D/RILJ    ( 1379): InCall VoicePrivacy is disabled
D/RILJ    ( 1379): [3158]< GET_CURRENT_CALLS  [id=1,ACTIVE,toa=145,norm,mo,0,voc,noevp,,cli=1,,0] 
...

Требуется найти строки с "GET_CURRENT_CALLS" и получить статус, в данном случае:

DIALING
ACTIVE

И да, в распоряжении grep, sed, awk, cut.
Признаюсь, пришлось повозиться.

echo "D/RILJ    ( 1379): [3554]< GET_CURRENT_CALLS  [id=1,ACTIVE,toa=145,norm,mt,0,voc,noevp,,cli=1,,0]" | sed -n 's/.*GET_CURRENT_CALLS[^,]*,\([^,]*\),.*/\1/p'

Некрасиво.

Нас невозможно сбить с пути, нам пофигу куда идти.

4

Re: sed, регулярные выражения

Приходилось подобное встречать. Представляю, каково это читать gui-ориентированному пользователю.

Некрасиво

По мне, так нормально.

sed -n 's/.*GET_CURRENT_CALLS[^,]*,\([^,]*\),.*/\1/p' FILENAME

Как вариант можно так:

grep GET_CURRENT_CALLS FILENAME | cut -d, -f2
perl -ne '/GET_CURRENT_CALLS[^,]+,([^,]+)/ && print $1' FILENAME

Из всех трех вариантов - вариант с sed лучше.

( 2 * b ) || ! ( 2 * b )

5 (изменено: DnsIs, 2013-10-01 19:29:07)

Re: sed, регулярные выражения

Так мне больше нравится, потому что перл может быть щедрым:

perl -ne "/GET_CURRENT_CALLS.+?,(.+?),/ && print $1" FILENAME
Нас невозможно сбить с пути, нам пофигу куда идти.

6

Re: sed, регулярные выражения

Полностью согласен. Я сам предпочитаю его, но он за собой "тащит" при загрузке кучу библиотек, что может вызвать некоторые "нарекания". Другой момент связанный с перлом, то что не многие его по началу понимают и часто решают некоторые задачи с помощью, например, awk или sed.

( 2 * b ) || ! ( 2 * b )

7

Re: sed, регулярные выражения

DnsIs пишет:

...потому что перл может быть щедрым...

Не только perl, ruby, например, также может быть полезным, а порой даже в чем-то превосхожить perl, однако, адепты последнего с презрением могут относиться к более молодым языкам.

Rumata пишет:

...но он за собой "тащит" при загрузке кучу библиотек...

Ну, не такую уж кучу.

Rumata пишет:

...что не многие его по началу понимают...

Не лукавьте: многим его просто влом изучать, во-первых, плюс еще в массах начинает крепнуть заблуждение, что perl уже давно дышит на ладан и изучать его не стоит, во-вторых. Однако perl жив, даже более того.

8

Re: sed, регулярные выражения

Опять GNU sed for windows шалит.

Например имеем файл test

8. "Ребята, напишите мне письмо"

Так работает

sed -n -e "s/^\([0-9]\)/0\1/gp" test > test2

А так нет

sed -n -e "s/\"//gp" test > test2
38. Ребята, напишите мне письмо
sed: can't read >: Invalid argument
sed: can't read test2: No such file or directory

От чего так?

Нас невозможно сбить с пути, нам пофигу куда идти.

9

Re: sed, регулярные выражения

Проблема экранирования кавычек внутри кавычек в консольном сеансе. Используйте код кавычек ASCII 34 (hex24)


echo 8. "Ребята, напишите мне письмо" | sed -n -e "s/\x24//gp"
( 2 * b ) || ! ( 2 * b )

10

Re: sed, регулярные выражения

Но ведь

sed -n -e "s/\"//gp" test

работает. Странный sed.

Нас невозможно сбить с пути, нам пофигу куда идти.

11 (изменено: yuriy2000, 2013-11-14 21:34:01)

Re: sed, регулярные выражения

Rumata пишет:

Проблема экранирования кавычек внутри кавычек в консольном сеансе. Используйте код кавычек ASCII 34 (hex24)


echo 8. "Ребята, напишите мне письмо" | sed -n -e "s/\x24//gp"

Маленькая ошибочка - код кавычки в HEX будет 0x22


echo 8. "Ребята, напишите мне письмо" | sed -n -e "s/\x22//gp"

12 (изменено: DnsIs, 2013-12-22 00:18:51)

Re: sed, регулярные выражения

Всех с наступащим НГ.

Sed меня не отпускает помогите пожалуйста. Есть файл:

03:30:44.617974 0us Beacon (GK Nauka) [1.0* 2.0* 5.5* 11.0* 9.0* 18.0* 36.0* 54.0* Mbit] ESS CH: 10, PRIVACY
    0x0000:  a1f2 5428 9e03 0000 6400 1104 0008 474b  ..T(....d.....GK
    0x0010:  204e 6175 6b61 0108 8284 8b96 92a4 c8ec  .Nauka..........
    0x0020:  0301 0a32 048c 98b0 e007 0654 5720 010d  ...2.......TW...
    0x0030:  1433 0820 0102 0304 0506 0733 0821 0506  .3.........3.!..
    0x0040:  0708 090a 0bdd 2700 50f2 0410 4a00 0110  ......'.P...J...
    0x0050:  1044 0001 0210 4700 1028 8028 8028 8018  0D....G..(.(.(..
    0x0060:  80a8 80b0 b2dc 5cc6 e210 3c00 0101 0506  ......\...<.....
    0x0070:  0001 0044 b010 2a01 042d 1aee 1117 ffff  ...D..*..-......
    0x0080:  0000 0100 0000 0000 0000 0000 0000 000c  ................
    0x0090:  0000 0000 003d 160a 0704 0000 0000 0000  .....=..........
    0x00a0:  0000 0000 0000 0000 0000 0000 0030 1801  .............0..
    0x00b0:  0000 0fac 0202 0000 0fac 0200 0fac 0401  ................
    0x00c0:  0000 0fac 0200 00dd 1800 50f2 0201 0100  ..........P.....
    0x00d0:  0003 a400 0027 a400 0042 435e 0062 322f  .....'...BC^.b2/
    0x00e0:  000b 0501 0006 127a dd07 000c 4304 0000  .......z....C...
    0x00f0:  00                                       .

Хочется видеть его в таком виде:

03:30:44.617974 0us Beacon (GK Nauka) [1.0* 2.0* 5.5* 11.0* 9.0* 18.0* 36.0* 54.0* Mbit] ESS CH: 10, PRIVACY
..T(....d.....GK.Nauka.............2.......TW....3.........3.!........'.P...J...0D....G..(.(.(........\...<........D..*..-...........................=.......................0............................P..........'...BC^.b2/.......z....C....

Удалить шестнадцетиричные значения

    xXxxxx:  xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx  

и главное переносы между строк только лишь в области данных, но не после заголовков (в данном примере должен остаться только один символ новой строки после PRIVACY)
В наличии Linux. Удаление лишнего реализовать можно так:

sed -e 's/\t.*\(.\{16\}\)$/\1/'

Удаление переносов как-то так:

sed -e ":a; /$/N; s/\n//; ta"

Но как соединить сие вместе и избежать удаления новой строки после PRIVACY?

UPD Собственно клин светом не сошелся на sed, в арсенале ведь весь linux.

Нас невозможно сбить с пути, нам пофигу куда идти.

13

Re: sed, регулярные выражения

Очень долго пашет, но таки работает.

sed ":start; s/\(.*\)[[:space:]]0x[a-h0-9]\{4\}:.*\s\s\(.\{,16\}\)$/\1\2/; tnext; b; :next; N; /0x[a-h0-9]\{4\}:/s/\n//; bstart"
Нас невозможно сбить с пути, нам пофигу куда идти.

14

Re: sed, регулярные выражения

Изменил акценты на выборку требуемых данных:
1. во всех строках кроме первой удалить начало строки, заканчивающееся двумя пробелами
2. все строки начиная со второй склеить в одну


sed -r -e '2,${s/.*  (.*)$/\1/}' FILENAME | sed -e '2,${:a; /$/N; s/\n//; ta}'

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


perl -ne 'BEGIN { $_ = <>; print; }; s/.*  (.*?)\s*$/$1/; print' FILENAME
( 2 * b ) || ! ( 2 * b )

15 (изменено: DnsIs, 2013-12-23 01:41:23)

Re: sed, регулярные выражения

На awk получилось на порядок быстрее.

awk '{if (/^\t/) {printf "%s", $NF} else {printf "\n"$0"\n"}}' | sed "/^$/d"

Ну слава богу, сам себе помог.
Спасибо всем.

Нас невозможно сбить с пути, нам пофигу куда идти.

16

Re: sed, регулярные выражения

Я как всегда олень. Rumata, вы должны простить меня. Данные исходные в таком вот виде (это лог tcpdump):

03:30:44.617974 0us Beacon (GK Nauka) [1.0* 2.0* 5.5* 11.0* 9.0* 18.0* 36.0* 54.0* Mbit] ESS CH: 10, PRIVACY
    0x0000:  a1f2 5428 9e03 0000 6400 1104 0008 474b  ..T(....d.....GK
    0x0010:  204e 6175 6b61 0108 8284 8b96 92a4 c8ec  .Nauka..........
    0x0020:  0301 0a32 048c 98b0 e007 0654 5720 010d  ...2.......TW...
    0x0030:  1433 0820 0102 0304 0506 0733 0821 0506  .3.........3.!..
    0x0040:  0708 090a 0bdd 2700 50f2 0410 4a00 0110  ......'.P...J...
    0x0050:  1044 0001 0210 4700 1028 8028 8028 8018  .D....G..(.(.(..
    0x0060:  80a8 80b0 b2dc 5cc6 e210 3c00 0101 0506  ......\...<.....
    0x0070:  0001 0044 b010 2a01 042d 1aee 1117 ffff  ...D..*..-......
    0x0080:  0000 0100 0000 0000 0000 0000 0000 000c  ................
    0x0090:  0000 0000 003d 160a 0704 0000 0000 0000  .....=..........
    0x00a0:  0000 0000 0000 0000 0000 0000 0030 1801  .............0..
    0x00b0:  0000 0fac 0202 0000 0fac 0200 0fac 0401  ................
    0x00c0:  0000 0fac 0200 00dd 1800 50f2 0201 0100  ..........P.....
    0x00d0:  0003 a400 0027 a400 0042 435e 0062 322f  .....'...BC^.b2/
    0x00e0:  000b 0501 0006 127a dd07 000c 4304 0000  .......z....C...
    0x00f0:  00                                       .
03:30:47.906724 0us Probe Request (Omentum) [1.0* 2.0* 5.5* 11.0* 6.0 12.0 24.0 36.0 Mbit]
    0x0000:  0007 4f6d 656e 7475 6d01 0882 848b 960c  ..Omentum.......
    0x0010:  1830 4832 0412 2460 6c                   .0H2..$`l
03:30:47.906726 0us Probe Request () [1.0* 2.0* 5.5* 11.0* 6.0 12.0 24.0 36.0 Mbit]
    0x0000:  0000 0108 8284 8b96 0c18 3048 3204 1224  ..........0H2..$
    0x0010:  606c                                     `l
03:30:50.463863 WEP Encrypted 0us Data IV:723616 Pad 20 KeyID 1
    0x0000:  1636 7260 2700 0000 aaaa 0300 0000 0800  .6r`'...........
    0x0010:  45c0 001c 5430 0000 0102 6141 c0a8 6305  E...T0....aA..c.
    0x0020:  e000 0001 1164 ee9b 0000 0000 0000 0000  .....d..........
    0x0030:  0000 0000 0000 0000 0000 0000 0000 3eb5  ..............>.
    0x0040:  934e 5323 af96 031d 44cf                 .NS#....D.

PS перед 0x0000 стоит табуляция.

Нас невозможно сбить с пути, нам пофигу куда идти.

17 (изменено: hvs, 2014-05-06 18:57:45)

Re: sed, регулярные выражения

DnsIs пишет:

На awk получилось на порядок быстрее.

awk '{if (/^\t/) {printf "%s", $NF} else {printf "\n"$0"\n"}}' | sed "/^$/d"

Ну слава богу, сам себе помог.
Спасибо всем.

Маленькое дополнение.
в стандартном CMD "фокус" с одиночными кавычками не проходит, к сожалению приходится использовать двойные: AWK (GAWK, NAWK) из пакета GNUWIN32 не воспринимает их в качестве определителя строки макроса. Аналогичная ситуация (в большинстве случаев) с другими утилитами по обработке текста из данного пакета.

Но все меняется, если данная конструкция запускается из PoSH. Все великолепно работает.

Резюме:
Связка GNUIWWIN32 + PoSH = гармония UNIX и Windows.

PS
Если кто-нибудь из уважаемого "ALL" знает способ обойти указанные ограничения CMD - буду премного благодарен.

18 (изменено: wisgest, 2014-05-09 07:27:30)

Re: sed, регулярные выражения

hvs пишет:

PS
Если кто-нибудь из уважаемого "ALL" знает способ обойти указанные ограничения CMD - буду премного благодарен.

Не совсем понятно, о каком ограничении речь. Но если это то, о чём я подумал, то, не вдаваясь в тонкости истолкования CMD своих спецсимволов попадающих и не попадаюших между кавычек, — заключать AWK-код в двойные кавычки, а содержащиеся в нём самом кавычки предварять «\». По крайней мере для GAWK.

19

Re: sed, регулярные выражения

Не совсем понятно, о каком ограничении речь.

Вот об этом:


C:\bin\tools>awk '{if (/^\t/) {printf "%s", $NF} else {printf "\n"$0"\n"}}' | sed "/^$/d"
awk: '{if
awk: ^ invalid char ''' in expression

Кстати, с GAWK тоже самое:


C:\bin\tools>gawk '{if (/^\t/) {printf "%s", $NF} else {printf "\n"$0"\n"}}' | sed "/^$/d"
gawk: '{if
gawk: ^ invalid char ''' in expression

20 (изменено: wisgest, 2014-05-09 14:02:10)

Re: sed, регулярные выражения

hvs пишет:

Не совсем понятно, о каком ограничении речь.

Вот об этом: <…>

Т.е. о котором я и ответил в #18.
Должно работать вот так:

gawk "{if (/^\t/) {printf \"%s\", $NF} else {printf \"\n\"$0\"\n\"}}" | sed "/^$/d"

Насчёт одиночных кавычек я думаю, что на самом деле AWK (и другие программы под UNIX) их не понимают — их обрабатывает командная оболочка прежде чем отдать командную строку запускаемой программе (так же как CMD предварительно обрабатывает символы «^»), преобразуя эту строку к чему-то подобному, что я показал выше.

21 (изменено: hvs, 2014-05-09 14:34:50)

Re: sed, регулярные выражения

Да, все верно, такой способ отрабатывает. Собственно, я его уже давно использую (с того момента, когда начал использовать пакет GNUWIN32).

Мой вопрос был в другом: есть ли способ использовать именно одиночные кавычки в качестве ограничителей макроса, а двойные внутри макроса в качестве определителя строк и выражений?

22 (изменено: Rumata, 2014-05-09 22:26:05)

Re: sed, регулярные выражения

Ответ - "нет".

В unix ограничителями строк являтся либо кавычки, либо апострофы. Поэтому следующие строки обе корректны и передаются в awk полностью как текст программы. Главное отличие заключается в том, что в первом случае строка интерпретируется, во втором - нет и передается как есть, без изменений.


awk "{ print }" FILENAME
awk '{ print }' FILENAME

В dos только кавычки являются ограничителями строк. В случае их отсутствия предполагается, что первый аргумент является программой, а остаток командной строки списком файлов. Это легко проверить, например:


awk /./{print} c:\Windows\System32\drivers\etc\hosts
awk /./ {print} c:\Windows\System32\drivers\etc\hosts

Первая команда корректно выведет все непустые строки заданного файла. Вторая - аварийно завершится сообщив о невозможности чтения файла {print}. Что весьма логично.

В простых случаях можно обойтись решением, удалив все пробелы в awk-команде (как в примерах выше). Иногда можно передать awk-команды через конвейер:


echo /./ { print } | awk -f - c:\Windows\System32\drivers\etc\hosts

Но этот способ не сработает если требуется обработать данные из конвейера же.

( 2 * b ) || ! ( 2 * b )

23

Re: sed, регулярные выражения

Rumata пишет:

В unix ограничителями строк являтся либо кавычки, либо апострофы.

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

Rumata пишет:

Поэтому следующие строки обе корректны и передаются в awk полностью как текст программы. Главное отличие заключается в том, что в первом случае строка интерпретируется, во втором - нет и передается как есть, без изменений.

awk "{ print }" FILENAME
awk '{ print }' FILENAME

Как я понимаю, как раз вторая строка преобразуется к первой перед передачей awk.
Вот что происходит с апострофами в WinZsh при передаче их вызываемой программе:

# cmd /c echo '123'
123
# cmd /c echo '1 2 3'
"1 2 3"
# cmd /c echo 1 " 2 " 3
1 " 2 " 3
# cmd /c echo '1"2"3'
1\"2\"3
# cmd /c echo ' 1"2"3 '
" 1\"2\"3 "
#

24 (изменено: Rumata, 2014-05-11 18:25:18)

Re: sed, регулярные выражения

не в самой Unix, а в обычно используемых в ней командных оболочках

Да. Так будет точнее.

Как я понимаю, как раз вторая строка преобразуется к первой перед передачей awk.

Скорее наоборот. "Строка в кавычках" интерполируется (подстановка и раскрытие переменных) и потом передается в awk. 'Строка в апострофах' передается на вход awk без изменений.

( 2 * b ) || ! ( 2 * b )